@babylonjs/lite 1.9.0 → 1.10.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 +26 -0
- package/dist/index.js +596 -526
- package/dist/index.js.map +1 -1
- package/index.d.ts +107 -4
- package/lib/engine/engine.js +1 -1
- package/lib/engine/engine.js.map +1 -1
- package/lib/frame-graph/render-task.js +6 -4
- package/lib/frame-graph/render-task.js.map +1 -1
- package/lib/index.js +4 -1
- package/lib/index.js.map +1 -1
- package/lib/loader-gltf/gltf-ext-quantization.js +4 -1
- package/lib/loader-gltf/gltf-ext-quantization.js.map +1 -1
- package/lib/loader-gltf/gltf-feature-registry.js +11 -1
- package/lib/loader-gltf/gltf-feature-registry.js.map +1 -1
- package/lib/loader-gltf/gltf-feature-variants.js +11 -1
- package/lib/loader-gltf/gltf-feature-variants.js.map +1 -1
- package/lib/loader-gltf/gltf-json-asset.js +8 -1
- package/lib/loader-gltf/gltf-json-asset.js.map +1 -1
- package/lib/loader-gltf/gltf-material.js +4 -29
- package/lib/loader-gltf/gltf-material.js.map +1 -1
- package/lib/loader-gltf/gltf-parser.js +1 -8
- package/lib/loader-gltf/gltf-parser.js.map +1 -1
- package/lib/loader-gltf/gltf-pbr-builder.js +1 -15
- package/lib/loader-gltf/gltf-pbr-builder.js.map +1 -1
- package/lib/loader-gltf/gltf-variants.js +5 -10
- package/lib/loader-gltf/gltf-variants.js.map +1 -1
- package/lib/loader-gltf/load-gltf.js +19 -29
- package/lib/loader-gltf/load-gltf.js.map +1 -1
- package/lib/material/pbr/background-dds-skybox.js +35 -93
- package/lib/material/pbr/background-dds-skybox.js.map +1 -1
- package/lib/material/pbr/background-ground.js +13 -18
- package/lib/material/pbr/background-ground.js.map +1 -1
- package/lib/material/pbr/background-hdr-skybox.js +35 -93
- package/lib/material/pbr/background-hdr-skybox.js.map +1 -1
- package/lib/material/pbr/background-solid-skybox.js +35 -93
- package/lib/material/pbr/background-solid-skybox.js.map +1 -1
- package/lib/material/pbr/fragments/clearcoat-fragment.js +5 -1
- package/lib/material/pbr/fragments/clearcoat-fragment.js.map +1 -1
- package/lib/material/pbr/fragments/iridescence-fragment.js +4 -1
- package/lib/material/pbr/fragments/iridescence-fragment.js.map +1 -1
- package/lib/material/pbr/fragments/refraction-rtt-fragment.js +7 -2
- package/lib/material/pbr/fragments/refraction-rtt-fragment.js.map +1 -1
- package/lib/material/pbr/fragments/sheen-fragment.js +2 -1
- package/lib/material/pbr/fragments/sheen-fragment.js.map +1 -1
- package/lib/material/pbr/fragments/subsurface-fragment.js +2 -1
- package/lib/material/pbr/fragments/subsurface-fragment.js.map +1 -1
- package/lib/material/pbr/fragments/unlit-fragment.js +1 -2
- package/lib/material/pbr/fragments/unlit-fragment.js.map +1 -1
- package/lib/material/pbr/pbr-compose.js +2 -0
- package/lib/material/pbr/pbr-compose.js.map +1 -1
- package/lib/material/pbr/pbr-flag-bits.js +1 -16
- package/lib/material/pbr/pbr-flag-bits.js.map +1 -1
- package/lib/material/pbr/pbr-flags.js +1 -1
- package/lib/material/pbr/pbr-fog-wgsl.js +1 -1
- package/lib/material/pbr/pbr-fog-wgsl.js.map +1 -1
- package/lib/material/pbr/pbr-geometry-output-shader.js +2 -1
- package/lib/material/pbr/pbr-geometry-output-shader.js.map +1 -1
- package/lib/material/pbr/pbr-geometry-view.js +2 -1
- package/lib/material/pbr/pbr-geometry-view.js.map +1 -1
- package/lib/material/pbr/pbr-renderable.js +4 -0
- package/lib/material/pbr/pbr-renderable.js.map +1 -1
- package/lib/material/pbr/pbr-template-gamma.js +7 -0
- package/lib/material/pbr/pbr-template-gamma.js.map +1 -0
- package/lib/material/pbr/pbr-template.js +2 -2
- package/lib/material/pbr/pbr-template.js.map +1 -1
- package/lib/material/standard/skybox-cubemap.js +1 -1
- package/lib/material/standard/skybox-cubemap.js.map +1 -1
- package/lib/material/standard/standard-template.js +1 -1
- package/lib/material/standard/standard-template.js.map +1 -1
- package/lib/mesh/GaussianSplatting/gaussian-splatting-pipeline-sh.js +3 -5
- package/lib/mesh/GaussianSplatting/gaussian-splatting-pipeline-sh.js.map +1 -1
- package/lib/mesh/GaussianSplatting/gaussian-splatting-pipeline.js +3 -5
- package/lib/mesh/GaussianSplatting/gaussian-splatting-pipeline.js.map +1 -1
- package/lib/particle/node/blocks/particle-condition-block.js +55 -0
- package/lib/particle/node/blocks/particle-condition-block.js.map +1 -0
- package/lib/particle/node/blocks/particle-float-to-int-block.js +28 -0
- package/lib/particle/node/blocks/particle-float-to-int-block.js.map +1 -0
- package/lib/particle/node/blocks/particle-gradient-block.js +32 -0
- package/lib/particle/node/blocks/particle-gradient-block.js.map +1 -0
- package/lib/particle/node/blocks/particle-gradient-value-block.js +11 -0
- package/lib/particle/node/blocks/particle-gradient-value-block.js.map +1 -0
- package/lib/particle/node/blocks/particle-lerp-block.js +2 -24
- package/lib/particle/node/blocks/particle-lerp-block.js.map +1 -1
- package/lib/particle/node/blocks/particle-lerp.js +27 -0
- package/lib/particle/node/blocks/particle-lerp.js.map +1 -0
- package/lib/particle/node/blocks/particle-vector-length-block.js +30 -0
- package/lib/particle/node/blocks/particle-vector-length-block.js.map +1 -0
- package/lib/particle/node/blocks/system-block.js +13 -3
- package/lib/particle/node/blocks/system-block.js.map +1 -1
- package/lib/particle/node/blocks/texture-source-block.js +2 -1
- package/lib/particle/node/blocks/texture-source-block.js.map +1 -1
- package/lib/particle/node/blocks/update-size-block.js +19 -0
- package/lib/particle/node/blocks/update-size-block.js.map +1 -0
- package/lib/particle/node/npe-build-state.js +10 -0
- package/lib/particle/node/npe-build-state.js.map +1 -1
- package/lib/particle/node/npe-registry.js +12 -0
- package/lib/particle/node/npe-registry.js.map +1 -1
- package/lib/particle/particle-system.js +7 -2
- package/lib/particle/particle-system.js.map +1 -1
- package/lib/picking/billboard-pick-pipeline.js +269 -0
- package/lib/picking/billboard-pick-pipeline.js.map +1 -0
- package/lib/picking/gpu-picker.js +37 -37
- package/lib/picking/gpu-picker.js.map +1 -1
- package/lib/picking/gs-picking-pipeline.js +26 -1
- package/lib/picking/gs-picking-pipeline.js.map +1 -1
- package/lib/picking/pick-contributor.js +13 -0
- package/lib/picking/pick-contributor.js.map +1 -0
- package/lib/picking/picking-info.js.map +1 -1
- package/lib/scene/scene-core.js +2 -2
- package/lib/scene/scene-core.js.map +1 -1
- package/lib/shader/wgsl-fog.js +18 -0
- package/lib/shader/wgsl-fog.js.map +1 -0
- package/lib/shader/wgsl-helpers.js +1 -16
- package/lib/shader/wgsl-helpers.js.map +1 -1
- package/lib/sprite/billboard-scene.js +2 -0
- package/lib/sprite/billboard-scene.js.map +1 -1
- package/lib/sprite/picking/pick-billboard.js +16 -0
- package/lib/sprite/picking/pick-billboard.js.map +1 -0
- package/lib/sprite/picking/pick-sprite-2d.js +41 -0
- package/lib/sprite/picking/pick-sprite-2d.js.map +1 -0
- package/lib/sprite/shared/sprite-atlas.js +4 -1
- package/lib/sprite/shared/sprite-atlas.js.map +1 -1
- package/lib/sprite/sprite-2d.js.map +1 -1
- package/lib/sprite/sprite-pipeline.js +18 -1
- package/lib/sprite/sprite-pipeline.js.map +1 -1
- package/lib/sprite/sprite-renderer.js +12 -6
- package/lib/sprite/sprite-renderer.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { U16, F32, I32, U8 } from '../../engine/typed-arrays.js';
|
|
2
2
|
import { BU, TU } from '../../engine/gpu-flags.js';
|
|
3
3
|
import { getOrCreateSampler } from '../../resource/gpu-pool.js';
|
|
4
4
|
import { createMappedBuffer, createUniformBuffer } from '../../resource/gpu-buffers.js';
|
|
@@ -14,142 +14,81 @@ const SKY_DDS_UNIFORM_SIZE = 96;
|
|
|
14
14
|
const DEFAULT_SKY_URL = "https://assets.babylonjs.com/core/environments/backgroundSkybox.dds";
|
|
15
15
|
function createSkyboxBuffers(engine, S) {
|
|
16
16
|
const positions = new F32([
|
|
17
|
-
S,
|
|
18
|
-
-S,
|
|
19
|
-
S,
|
|
20
|
-
-S,
|
|
21
|
-
-S,
|
|
22
|
-
S,
|
|
23
|
-
-S,
|
|
24
|
-
S,
|
|
25
|
-
S,
|
|
26
|
-
S,
|
|
27
|
-
S,
|
|
28
|
-
S,
|
|
29
|
-
S,
|
|
30
|
-
S,
|
|
31
|
-
-S,
|
|
32
|
-
-S,
|
|
33
|
-
S,
|
|
34
|
-
-S,
|
|
35
|
-
-S,
|
|
36
17
|
-S,
|
|
37
18
|
-S,
|
|
38
|
-
S,
|
|
39
|
-
-S,
|
|
40
19
|
-S,
|
|
41
20
|
S,
|
|
42
|
-
S,
|
|
43
21
|
-S,
|
|
44
|
-
S,
|
|
45
22
|
-S,
|
|
46
23
|
-S,
|
|
47
24
|
S,
|
|
48
25
|
-S,
|
|
49
26
|
S,
|
|
50
27
|
S,
|
|
51
|
-
S,
|
|
52
|
-
S,
|
|
53
28
|
-S,
|
|
54
|
-
S,
|
|
55
|
-
S,
|
|
56
29
|
-S,
|
|
57
30
|
-S,
|
|
58
31
|
S,
|
|
59
|
-
-S,
|
|
60
|
-
-S,
|
|
61
|
-
-S,
|
|
62
|
-
-S,
|
|
63
32
|
S,
|
|
64
33
|
-S,
|
|
65
|
-
-S,
|
|
66
|
-
S,
|
|
67
|
-
S,
|
|
68
|
-
-S,
|
|
69
|
-
S,
|
|
70
|
-
-S,
|
|
71
|
-
S,
|
|
72
34
|
S,
|
|
73
35
|
-S,
|
|
74
36
|
S,
|
|
75
37
|
S,
|
|
76
38
|
S,
|
|
77
39
|
S,
|
|
78
|
-
-S,
|
|
79
|
-
S,
|
|
80
|
-
S,
|
|
81
|
-
-S,
|
|
82
|
-
-S,
|
|
83
|
-
-S,
|
|
84
|
-
-S,
|
|
85
|
-
-S,
|
|
86
|
-
-S,
|
|
87
|
-
-S,
|
|
88
40
|
S
|
|
89
41
|
]);
|
|
90
42
|
const indices = new U16([
|
|
43
|
+
6,
|
|
44
|
+
4,
|
|
45
|
+
5,
|
|
46
|
+
7,
|
|
47
|
+
6,
|
|
48
|
+
5,
|
|
49
|
+
0,
|
|
91
50
|
2,
|
|
51
|
+
3,
|
|
92
52
|
1,
|
|
93
53
|
0,
|
|
94
54
|
3,
|
|
55
|
+
5,
|
|
56
|
+
1,
|
|
57
|
+
3,
|
|
58
|
+
7,
|
|
59
|
+
5,
|
|
60
|
+
3,
|
|
61
|
+
0,
|
|
62
|
+
4,
|
|
63
|
+
6,
|
|
95
64
|
2,
|
|
96
65
|
0,
|
|
97
66
|
6,
|
|
98
|
-
|
|
99
|
-
|
|
67
|
+
3,
|
|
68
|
+
2,
|
|
69
|
+
6,
|
|
100
70
|
7,
|
|
71
|
+
3,
|
|
101
72
|
6,
|
|
73
|
+
0,
|
|
74
|
+
1,
|
|
75
|
+
5,
|
|
102
76
|
4,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
8,
|
|
106
|
-
11,
|
|
107
|
-
10,
|
|
108
|
-
8,
|
|
109
|
-
14,
|
|
110
|
-
13,
|
|
111
|
-
12,
|
|
112
|
-
15,
|
|
113
|
-
14,
|
|
114
|
-
12,
|
|
115
|
-
18,
|
|
116
|
-
17,
|
|
117
|
-
16,
|
|
118
|
-
19,
|
|
119
|
-
18,
|
|
120
|
-
16,
|
|
121
|
-
22,
|
|
122
|
-
21,
|
|
123
|
-
20,
|
|
124
|
-
23,
|
|
125
|
-
22,
|
|
126
|
-
20
|
|
77
|
+
0,
|
|
78
|
+
5
|
|
127
79
|
]);
|
|
128
80
|
return {
|
|
129
81
|
posBuffer: createMappedBuffer(engine, positions, BU.VERTEX),
|
|
130
|
-
idxBuffer: createMappedBuffer(engine, indices, BU.INDEX)
|
|
131
|
-
idxCount: 36
|
|
82
|
+
idxBuffer: createMappedBuffer(engine, indices, BU.INDEX)
|
|
132
83
|
};
|
|
133
84
|
}
|
|
134
|
-
function buildSkyboxWorldMatrix(rootPosition) {
|
|
135
|
-
const world = new F32(16);
|
|
136
|
-
world[0] = 1;
|
|
137
|
-
world[5] = 1;
|
|
138
|
-
world[10] = 1;
|
|
139
|
-
world[15] = 1;
|
|
140
|
-
world[12] = rootPosition[0];
|
|
141
|
-
world[13] = rootPosition[1];
|
|
142
|
-
world[14] = rootPosition[2];
|
|
143
|
-
return world;
|
|
144
|
-
}
|
|
145
85
|
async function buildDdsSkyboxRenderable(scene, skyHalfSize, rootPosition, primaryColor, skyboxTextureUrl, enableNoise = true) {
|
|
146
86
|
const engine = scene.surface.engine;
|
|
147
|
-
const skyboxWorld = buildSkyboxWorldMatrix(rootPosition);
|
|
148
87
|
const skyBufs = createSkyboxBuffers(engine, skyHalfSize);
|
|
149
88
|
const { cubeView, sampler } = await loadDdsCube(engine, skyboxTextureUrl ?? DEFAULT_SKY_URL);
|
|
150
89
|
const fragCode = SCENE_UBO_WGSL + (enableNoise ? WGSL_DITHER : WGSL_NO_DITHER) + ddsSkyboxFragSrc;
|
|
151
90
|
const mat = createCubemapSkyboxMaterial(enableNoise ? "skybox-dds" : "skybox-dds0", SCENE_UBO_WGSL + ddsSkyboxVertSrc, fragCode);
|
|
152
|
-
const ubo = createDdsMeshUBO(engine,
|
|
91
|
+
const ubo = createDdsMeshUBO(engine, rootPosition, primaryColor, scene.imageProcessing.exposure, scene.imageProcessing.contrast);
|
|
153
92
|
const bindGroup = mat.createBindGroup(engine, ubo, cubeView, sampler);
|
|
154
93
|
const r = {
|
|
155
94
|
order: 0,
|
|
@@ -162,7 +101,7 @@ async function buildDdsSkyboxRenderable(scene, skyHalfSize, rootPosition, primar
|
|
|
162
101
|
pass.setBindGroup(1, bindGroup);
|
|
163
102
|
pass.setVertexBuffer(0, skyBufs.posBuffer);
|
|
164
103
|
pass.setIndexBuffer(skyBufs.idxBuffer, "uint16");
|
|
165
|
-
pass.drawIndexed(
|
|
104
|
+
pass.drawIndexed(36);
|
|
166
105
|
return 1;
|
|
167
106
|
}
|
|
168
107
|
};
|
|
@@ -170,9 +109,12 @@ async function buildDdsSkyboxRenderable(scene, skyHalfSize, rootPosition, primar
|
|
|
170
109
|
};
|
|
171
110
|
return r;
|
|
172
111
|
}
|
|
173
|
-
function createDdsMeshUBO(engine,
|
|
112
|
+
function createDdsMeshUBO(engine, rootPosition, primaryColor, exposureLinear, contrast) {
|
|
174
113
|
const data = new F32(SKY_DDS_UNIFORM_SIZE / 4);
|
|
175
|
-
data
|
|
114
|
+
data[0] = data[5] = data[10] = data[15] = 1;
|
|
115
|
+
data[12] = rootPosition[0];
|
|
116
|
+
data[13] = rootPosition[1];
|
|
117
|
+
data[14] = rootPosition[2];
|
|
176
118
|
data[16] = primaryColor[0];
|
|
177
119
|
data[17] = primaryColor[1];
|
|
178
120
|
data[18] = primaryColor[2];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"background-dds-skybox.js","sources":["../../../../shaders/skybox-dds.vertex.wgsl?raw","../../../../shaders/skybox-dds.fragment.wgsl?raw","../../../../src/material/pbr/background-dds-skybox.ts"],"sourcesContent":["export default \"// DDS Skybox Vertex Shader — standard world transform.\\n// positionUVW uses local position for cube direction lookup.\\n\\nstruct MeshUniforms {\\n world: mat4x4<f32>,\\n};\\n\\n@group(1) @binding(0) var<uniform> mesh: MeshUniforms;\\n\\nstruct VertexOutput {\\n @builtin(position) clipPos: vec4<f32>,\\n @location(0) positionUVW: vec3<f32>,\\n @location(1) positionW: vec3<f32>,\\n};\\n\\n@vertex\\nfn main(@location(0) position: vec3<f32>) -> VertexOutput {\\n var output: VertexOutput;\\n output.positionUVW = position;\\n let worldPos = (mesh.world * vec4<f32>(position, 1.0)).xyz;\\n output.positionW = worldPos;\\n output.clipPos = scene.viewProjection * vec4<f32>(worldPos, 1.0);\\n return output;\\n}\\n\"","export default \"// DDS Cube Skybox Fragment Shader — samples DDS cube texture with BJS image processing.\\n// Used by scenes that load backgroundSkybox.dds (createDefaultEnvironment).\\n// Pipeline: exposure → Reinhard tonemap → gamma → contrast → dither.\\n\\nstruct MeshUniforms {\\n world: mat4x4<f32>,\\n primaryColor: vec3<f32>,\\n exposureLinear: f32,\\n contrast: f32,\\n _pad1: f32,\\n _pad2: f32,\\n _pad3: f32,\\n};\\n\\n@group(1) @binding(0) var<uniform> mesh: MeshUniforms;\\n@group(1) @binding(1) var envCubemap: texture_cube<f32>;\\n@group(1) @binding(2) var envSampler: sampler;\\n\\nstruct FragmentInput {\\n @location(0) positionUVW: vec3<f32>,\\n @location(1) positionW: vec3<f32>,\\n};\\n\\n@fragment\\nfn main(input: FragmentInput) -> @location(0) vec4<f32> {\\n let dir = normalize(input.positionUVW);\\n var color = textureSampleLevel(envCubemap, envSampler, dir, 0.0).rgb;\\n\\n // BJS BackgroundMaterial: colorBase = reflectionColor.rgb * primaryColor.rgb\\n color *= mesh.primaryColor;\\n\\n if (scene.vImageInfos.w >= 0.0) {\\n // Exposure\\n color *= mesh.exposureLinear;\\n // Reinhard tonemap (matches BJS toneMappingType 0)\\n color = 1.0 - exp2(-1.590579 * color);\\n // Gamma\\n color = pow(color, vec3<f32>(1.0 / 2.2));\\n color = saturate(color);\\n\\n // Contrast\\n let highContrast = color * color * (3.0 - 2.0 * color);\\n color = mix(color, highContrast, mesh.contrast - 1.0);\\n\\n // Dithering (enableNoise=true, variance=0.5)\\n color = color + vec3<f32>(dither(input.positionW.xy, 0.5));\\n color = max(color, vec3<f32>(0.0));\\n }\\n\\n return vec4<f32>(color, 1.0);\\n}\\n\"","/** DDS cube skybox — lazy-loaded only when skyboxUrl ends with .dds.\n * Loads backgroundSkybox.dds and renders it with BJS image processing. */\n\nimport { F32, I32, U16, U8 } from \"../../engine/typed-arrays.js\";\nimport { TU, BU } from \"../../engine/gpu-flags.js\";\nimport type { SceneContext } from \"../../scene/scene.js\";\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { Renderable } from \"../../render/renderable.js\";\nimport { getOrCreateSampler } from \"../../resource/gpu-pool.js\";\nimport { createMappedBuffer, createUniformBuffer } from \"../../resource/gpu-buffers.js\";\nimport { WGSL_DITHER, WGSL_NO_DITHER } from \"../../shader/wgsl-helpers.js\";\nimport { SCENE_UBO_WGSL } from \"../../shader/scene-uniforms.js\";\nimport { createCubemapSkyboxMaterial } from \"./cubemap-skybox-material.js\";\nimport ddsSkyboxVertSrc from \"../../../shaders/skybox-dds.vertex.wgsl?raw\";\nimport ddsSkyboxFragSrc from \"../../../shaders/skybox-dds.fragment.wgsl?raw\";\n\nconst SKY_DDS_UNIFORM_SIZE = 96;\nconst DEFAULT_SKY_URL = \"https://assets.babylonjs.com/core/environments/backgroundSkybox.dds\";\n\nfunction createSkyboxBuffers(engine: EngineContext, S: number): { posBuffer: GPUBuffer; idxBuffer: GPUBuffer; idxCount: number } {\n // prettier-ignore\n const positions = new F32([\n S,-S, S, -S,-S, S, -S, S, S, S, S, S,\n S, S,-S, -S, S,-S, -S,-S,-S, S,-S,-S,\n S, S,-S, S,-S,-S, S,-S, S, S, S, S,\n -S, S, S, -S,-S, S, -S,-S,-S, -S, S,-S,\n -S, S, S, -S, S,-S, S, S,-S, S, S, S,\n S,-S, S, S,-S,-S, -S,-S,-S, -S,-S, S,\n ]);\n // prettier-ignore\n const indices = new U16([\n 2, 1, 0, 3, 2, 0, 6, 5, 4, 7, 6, 4,\n 10, 9, 8, 11,10, 8, 14,13,12, 15,14,12,\n 18,17,16, 19,18,16, 22,21,20, 23,22,20,\n ]);\n return {\n posBuffer: createMappedBuffer(engine, positions, BU.VERTEX),\n idxBuffer: createMappedBuffer(engine, indices, BU.INDEX),\n idxCount: 36,\n };\n}\n\nfunction buildSkyboxWorldMatrix(rootPosition: [number, number, number]): Float32Array {\n const world = new F32(16);\n world[0] = 1;\n world[5] = 1;\n world[10] = 1;\n world[15] = 1;\n world[12] = rootPosition[0];\n world[13] = rootPosition[1];\n world[14] = rootPosition[2];\n return world;\n}\n\n/** Build a DDS cube skybox as a complete Renderable (order 0). */\nexport async function buildDdsSkyboxRenderable(\n scene: SceneContext,\n skyHalfSize: number,\n rootPosition: [number, number, number],\n primaryColor: [number, number, number],\n skyboxTextureUrl?: string,\n enableNoise = true\n): Promise<Renderable> {\n const engine = scene.surface.engine;\n\n const skyboxWorld = buildSkyboxWorldMatrix(rootPosition);\n\n const skyBufs = createSkyboxBuffers(engine, skyHalfSize);\n const { cubeView, sampler } = await loadDdsCube(engine, skyboxTextureUrl ?? DEFAULT_SKY_URL);\n\n const fragCode = SCENE_UBO_WGSL + (enableNoise ? WGSL_DITHER : WGSL_NO_DITHER) + ddsSkyboxFragSrc;\n const mat = createCubemapSkyboxMaterial(enableNoise ? \"skybox-dds\" : \"skybox-dds0\", SCENE_UBO_WGSL + ddsSkyboxVertSrc, fragCode);\n const ubo = createDdsMeshUBO(engine, skyboxWorld, primaryColor, scene.imageProcessing.exposure, scene.imageProcessing.contrast);\n const bindGroup = mat.createBindGroup(engine, ubo, cubeView, sampler);\n\n const r: Renderable = {\n order: 0,\n isTransparent: false,\n bind(eng, sig) {\n return {\n renderable: r,\n pipeline: mat.getPipeline(eng as EngineContext, sig),\n draw(pass) {\n pass.setBindGroup(1, bindGroup);\n pass.setVertexBuffer(0, skyBufs.posBuffer);\n pass.setIndexBuffer(skyBufs.idxBuffer, \"uint16\");\n pass.drawIndexed(skyBufs.idxCount);\n return 1;\n },\n };\n },\n };\n return r;\n}\n\n// ─── DDS Skybox UBO ──────────────────────────────────────────────────────────\n\nfunction createDdsMeshUBO(engine: EngineContext, world: Float32Array, primaryColor: [number, number, number], exposureLinear: number, contrast: number): GPUBuffer {\n const data = new F32(SKY_DDS_UNIFORM_SIZE / 4);\n data.set(world, 0);\n data[16] = primaryColor[0];\n data[17] = primaryColor[1];\n data[18] = primaryColor[2];\n data[19] = exposureLinear;\n data[20] = contrast;\n return createUniformBuffer(engine, data);\n}\n\n// ─── DDS Cube Texture Loader ─────────────────────────────────────────────────\n\n/** Load a DDS cube texture (rgba16float) and return a cube texture view + sampler.\n * Uploads only mip 0 from the DDS file and generates remaining mipmaps on the\n * GPU so that cube face edges blend seamlessly — matching BJS's behaviour. */\nasync function loadDdsCube(engine: EngineContext, url: string): Promise<{ cubeView: GPUTextureView; sampler: GPUSampler }> {\n const device = engine._device;\n const buf = await (await fetch(url)).arrayBuffer();\n const header = new I32(buf, 0, 32);\n const width = header[3]!;\n const height = header[4]!;\n const mipCount = Math.max(header[7]!, 1);\n\n // DDS pixel format offset 76..107 — for rgba16float, FourCC = 'DX10'\n // DDS_HEADER_DX10 at byte 128: dxgiFormat, resourceDimension, miscFlag, arraySize, etc.\n // For cube: miscFlag has RESOURCE_MISC_TEXTURECUBE (0x4), arraySize = 1 (6 faces in data)\n const dataOffset = header[21] === 0x30315844 /* 'DX10' */ ? 128 + 20 : 128;\n const raw = new U8(buf, dataOffset);\n\n const fmt: GPUTextureFormat = \"rgba16float\";\n const tex = device.createTexture({\n size: [width, height, 6],\n format: fmt,\n mipLevelCount: mipCount,\n usage: TU.TEXTURE_BINDING | TU.COPY_DST | TU.RENDER_ATTACHMENT,\n dimension: \"2d\",\n });\n\n // Upload all mip levels for each face from the DDS (face-major layout).\n // Even though the skybox shader samples mip 0 explicitly, uploading all\n // mips avoids the need for GPU-side mipmap generation.\n let offset = 0;\n for (let face = 0; face < 6; face++) {\n for (let m = 0; m < mipCount; m++) {\n const s = Math.max(width >> m, 1);\n device.queue.writeTexture(\n { texture: tex, origin: { x: 0, y: 0, z: face }, mipLevel: m },\n raw.buffer,\n { offset: raw.byteOffset + offset, bytesPerRow: s * 8 },\n { width: s, height: s }\n );\n offset += s * s * 8;\n }\n }\n\n const cubeView = tex.createView({ dimension: \"cube\" });\n const sampler = getOrCreateSampler(engine, {\n magFilter: \"linear\",\n minFilter: \"linear\",\n mipmapFilter: \"linear\",\n addressModeU: \"clamp-to-edge\",\n addressModeV: \"clamp-to-edge\",\n addressModeW: \"clamp-to-edge\",\n maxAnisotropy: 4,\n });\n\n return { cubeView, sampler };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"background-dds-skybox.js","sources":["../../../../shaders/skybox-dds.vertex.wgsl?raw","../../../../shaders/skybox-dds.fragment.wgsl?raw","../../../../src/material/pbr/background-dds-skybox.ts"],"sourcesContent":["export default \"// DDS Skybox Vertex Shader — standard world transform.\\n// positionUVW uses local position for cube direction lookup.\\n\\nstruct MeshUniforms {\\n world: mat4x4<f32>,\\n};\\n\\n@group(1) @binding(0) var<uniform> mesh: MeshUniforms;\\n\\nstruct VertexOutput {\\n @builtin(position) clipPos: vec4<f32>,\\n @location(0) positionUVW: vec3<f32>,\\n @location(1) positionW: vec3<f32>,\\n};\\n\\n@vertex\\nfn main(@location(0) position: vec3<f32>) -> VertexOutput {\\n var output: VertexOutput;\\n output.positionUVW = position;\\n let worldPos = (mesh.world * vec4<f32>(position, 1.0)).xyz;\\n output.positionW = worldPos;\\n output.clipPos = scene.viewProjection * vec4<f32>(worldPos, 1.0);\\n return output;\\n}\\n\"","export default \"// DDS Cube Skybox Fragment Shader — samples DDS cube texture with BJS image processing.\\n// Used by scenes that load backgroundSkybox.dds (createDefaultEnvironment).\\n// Pipeline: exposure → Reinhard tonemap → gamma → contrast → dither.\\n\\nstruct MeshUniforms {\\n world: mat4x4<f32>,\\n primaryColor: vec3<f32>,\\n exposureLinear: f32,\\n contrast: f32,\\n _pad1: f32,\\n _pad2: f32,\\n _pad3: f32,\\n};\\n\\n@group(1) @binding(0) var<uniform> mesh: MeshUniforms;\\n@group(1) @binding(1) var envCubemap: texture_cube<f32>;\\n@group(1) @binding(2) var envSampler: sampler;\\n\\nstruct FragmentInput {\\n @location(0) positionUVW: vec3<f32>,\\n @location(1) positionW: vec3<f32>,\\n};\\n\\n@fragment\\nfn main(input: FragmentInput) -> @location(0) vec4<f32> {\\n let dir = normalize(input.positionUVW);\\n var color = textureSampleLevel(envCubemap, envSampler, dir, 0.0).rgb;\\n\\n // BJS BackgroundMaterial: colorBase = reflectionColor.rgb * primaryColor.rgb\\n color *= mesh.primaryColor;\\n\\n if (scene.vImageInfos.w >= 0.0) {\\n // Exposure\\n color *= mesh.exposureLinear;\\n // Reinhard tonemap (matches BJS toneMappingType 0)\\n color = 1.0 - exp2(-1.590579 * color);\\n // Gamma\\n color = pow(color, vec3<f32>(1.0 / 2.2));\\n color = saturate(color);\\n\\n // Contrast\\n let highContrast = color * color * (3.0 - 2.0 * color);\\n color = mix(color, highContrast, mesh.contrast - 1.0);\\n\\n // Dithering (enableNoise=true, variance=0.5)\\n color = color + vec3<f32>(dither(input.positionW.xy, 0.5));\\n color = max(color, vec3<f32>(0.0));\\n }\\n\\n return vec4<f32>(color, 1.0);\\n}\\n\"","/** DDS cube skybox — lazy-loaded only when skyboxUrl ends with .dds.\n * Loads backgroundSkybox.dds and renders it with BJS image processing. */\n\nimport { F32, I32, U16, U8 } from \"../../engine/typed-arrays.js\";\nimport { TU, BU } from \"../../engine/gpu-flags.js\";\nimport type { SceneContext } from \"../../scene/scene.js\";\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { Renderable } from \"../../render/renderable.js\";\nimport { getOrCreateSampler } from \"../../resource/gpu-pool.js\";\nimport { createMappedBuffer, createUniformBuffer } from \"../../resource/gpu-buffers.js\";\nimport { WGSL_DITHER, WGSL_NO_DITHER } from \"../../shader/wgsl-helpers.js\";\nimport { SCENE_UBO_WGSL } from \"../../shader/scene-uniforms.js\";\nimport { createCubemapSkyboxMaterial } from \"./cubemap-skybox-material.js\";\nimport ddsSkyboxVertSrc from \"../../../shaders/skybox-dds.vertex.wgsl?raw\";\nimport ddsSkyboxFragSrc from \"../../../shaders/skybox-dds.fragment.wgsl?raw\";\n\nconst SKY_DDS_UNIFORM_SIZE = 96;\nconst DEFAULT_SKY_URL = \"https://assets.babylonjs.com/core/environments/backgroundSkybox.dds\";\n\nfunction createSkyboxBuffers(engine: EngineContext, S: number): { posBuffer: GPUBuffer; idxBuffer: GPUBuffer } {\n // prettier-ignore\n const positions = new F32([\n -S,-S,-S, S,-S,-S, -S, S,-S, S, S,-S,\n -S,-S, S, S,-S, S, -S, S, S, S, S, S,\n ]);\n // prettier-ignore\n const indices = new U16([\n 6,4,5, 7,6,5, 0,2,3, 1,0,3,\n 5,1,3, 7,5,3, 0,4,6, 2,0,6,\n 3,2,6, 7,3,6, 0,1,5, 4,0,5,\n ]);\n return {\n posBuffer: createMappedBuffer(engine, positions, BU.VERTEX),\n idxBuffer: createMappedBuffer(engine, indices, BU.INDEX),\n };\n}\n\n/** Build a DDS cube skybox as a complete Renderable (order 0). */\nexport async function buildDdsSkyboxRenderable(\n scene: SceneContext,\n skyHalfSize: number,\n rootPosition: [number, number, number],\n primaryColor: [number, number, number],\n skyboxTextureUrl?: string,\n enableNoise = true\n): Promise<Renderable> {\n const engine = scene.surface.engine;\n\n const skyBufs = createSkyboxBuffers(engine, skyHalfSize);\n const { cubeView, sampler } = await loadDdsCube(engine, skyboxTextureUrl ?? DEFAULT_SKY_URL);\n\n const fragCode = SCENE_UBO_WGSL + (enableNoise ? WGSL_DITHER : WGSL_NO_DITHER) + ddsSkyboxFragSrc;\n const mat = createCubemapSkyboxMaterial(enableNoise ? \"skybox-dds\" : \"skybox-dds0\", SCENE_UBO_WGSL + ddsSkyboxVertSrc, fragCode);\n const ubo = createDdsMeshUBO(engine, rootPosition, primaryColor, scene.imageProcessing.exposure, scene.imageProcessing.contrast);\n const bindGroup = mat.createBindGroup(engine, ubo, cubeView, sampler);\n\n const r: Renderable = {\n order: 0,\n isTransparent: false,\n bind(eng, sig) {\n return {\n renderable: r,\n pipeline: mat.getPipeline(eng as EngineContext, sig),\n draw(pass) {\n pass.setBindGroup(1, bindGroup);\n pass.setVertexBuffer(0, skyBufs.posBuffer);\n pass.setIndexBuffer(skyBufs.idxBuffer, \"uint16\");\n pass.drawIndexed(36);\n return 1;\n },\n };\n },\n };\n return r;\n}\n\n// ─── DDS Skybox UBO ──────────────────────────────────────────────────────────\n\nfunction createDdsMeshUBO(\n engine: EngineContext,\n rootPosition: [number, number, number],\n primaryColor: [number, number, number],\n exposureLinear: number,\n contrast: number\n): GPUBuffer {\n const data = new F32(SKY_DDS_UNIFORM_SIZE / 4);\n data[0] = data[5] = data[10] = data[15] = 1;\n data[12] = rootPosition[0];\n data[13] = rootPosition[1];\n data[14] = rootPosition[2];\n data[16] = primaryColor[0];\n data[17] = primaryColor[1];\n data[18] = primaryColor[2];\n data[19] = exposureLinear;\n data[20] = contrast;\n return createUniformBuffer(engine, data);\n}\n\n// ─── DDS Cube Texture Loader ─────────────────────────────────────────────────\n\n/** Load a DDS cube texture (rgba16float) and return a cube texture view + sampler.\n * Uploads only mip 0 from the DDS file and generates remaining mipmaps on the\n * GPU so that cube face edges blend seamlessly — matching BJS's behaviour. */\nasync function loadDdsCube(engine: EngineContext, url: string): Promise<{ cubeView: GPUTextureView; sampler: GPUSampler }> {\n const device = engine._device;\n const buf = await (await fetch(url)).arrayBuffer();\n const header = new I32(buf, 0, 32);\n const width = header[3]!;\n const height = header[4]!;\n const mipCount = Math.max(header[7]!, 1);\n\n // DDS pixel format offset 76..107 — for rgba16float, FourCC = 'DX10'\n // DDS_HEADER_DX10 at byte 128: dxgiFormat, resourceDimension, miscFlag, arraySize, etc.\n // For cube: miscFlag has RESOURCE_MISC_TEXTURECUBE (0x4), arraySize = 1 (6 faces in data)\n const dataOffset = header[21] === 0x30315844 /* 'DX10' */ ? 128 + 20 : 128;\n const raw = new U8(buf, dataOffset);\n\n const fmt: GPUTextureFormat = \"rgba16float\";\n const tex = device.createTexture({\n size: [width, height, 6],\n format: fmt,\n mipLevelCount: mipCount,\n usage: TU.TEXTURE_BINDING | TU.COPY_DST | TU.RENDER_ATTACHMENT,\n dimension: \"2d\",\n });\n\n // Upload all mip levels for each face from the DDS (face-major layout).\n // Even though the skybox shader samples mip 0 explicitly, uploading all\n // mips avoids the need for GPU-side mipmap generation.\n let offset = 0;\n for (let face = 0; face < 6; face++) {\n for (let m = 0; m < mipCount; m++) {\n const s = Math.max(width >> m, 1);\n device.queue.writeTexture(\n { texture: tex, origin: { x: 0, y: 0, z: face }, mipLevel: m },\n raw.buffer,\n { offset: raw.byteOffset + offset, bytesPerRow: s * 8 },\n { width: s, height: s }\n );\n offset += s * s * 8;\n }\n }\n\n const cubeView = tex.createView({ dimension: \"cube\" });\n const sampler = getOrCreateSampler(engine, {\n magFilter: \"linear\",\n minFilter: \"linear\",\n mipmapFilter: \"linear\",\n addressModeU: \"clamp-to-edge\",\n addressModeV: \"clamp-to-edge\",\n addressModeW: \"clamp-to-edge\",\n maxAnisotropy: 4,\n });\n\n return { cubeView, sampler };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { U16, F32, U8 } from '../../engine/typed-arrays.js';
|
|
2
2
|
import { BU, TU, SS } from '../../engine/gpu-flags.js';
|
|
3
3
|
import { getBilinearSampler } from '../../resource/samplers.js';
|
|
4
4
|
import { createMappedBuffer, createUniformBuffer } from '../../resource/gpu-buffers.js';
|
|
@@ -33,19 +33,8 @@ const BG_MESH_UNIFORM_SIZE = 96;
|
|
|
33
33
|
async function buildGroundRenderable(engine, groundSize, rootPosition, primaryColor, groundTextureUrl, groundImagePromise, enableNoise = true) {
|
|
34
34
|
const fragCode = SCENE_UBO_WGSL + WGSL_IMAGE_PROCESSING + (enableNoise ? WGSL_DITHER : WGSL_NO_DITHER) + groundFragSrc;
|
|
35
35
|
const gndMat = createGroundMaterial(enableNoise, fragCode);
|
|
36
|
-
const eps = 2220446049250313e-31;
|
|
37
|
-
const groundWorld = new F32(16);
|
|
38
|
-
groundWorld[0] = 1;
|
|
39
|
-
groundWorld[5] = eps;
|
|
40
|
-
groundWorld[6] = -1;
|
|
41
|
-
groundWorld[9] = 1;
|
|
42
|
-
groundWorld[10] = eps;
|
|
43
|
-
groundWorld[12] = rootPosition[0];
|
|
44
|
-
groundWorld[13] = rootPosition[1];
|
|
45
|
-
groundWorld[14] = rootPosition[2];
|
|
46
|
-
groundWorld[15] = 1;
|
|
47
36
|
const gndBufs = createGroundBuffers(engine, groundSize);
|
|
48
|
-
const gndUBO = createBgMeshUBO(engine,
|
|
37
|
+
const gndUBO = createBgMeshUBO(engine, rootPosition, primaryColor);
|
|
49
38
|
const groundTex = await loadGroundTexture(engine, groundTextureUrl, groundImagePromise);
|
|
50
39
|
const groundTexView = groundTex.createView();
|
|
51
40
|
const groundSamp = getBilinearSampler(engine);
|
|
@@ -64,7 +53,7 @@ async function buildGroundRenderable(engine, groundSize, rootPosition, primaryCo
|
|
|
64
53
|
pass.setVertexBuffer(1, gndBufs.normBuffer);
|
|
65
54
|
pass.setVertexBuffer(2, gndBufs.uvBuffer);
|
|
66
55
|
pass.setIndexBuffer(gndBufs.idxBuffer, "uint16");
|
|
67
|
-
pass.drawIndexed(
|
|
56
|
+
pass.drawIndexed(6);
|
|
68
57
|
return 1;
|
|
69
58
|
}
|
|
70
59
|
};
|
|
@@ -201,13 +190,19 @@ function createGroundBuffers(engine, groundSize) {
|
|
|
201
190
|
posBuffer: createMappedBuffer(engine, positions, BU.VERTEX),
|
|
202
191
|
normBuffer: createMappedBuffer(engine, normals, BU.VERTEX),
|
|
203
192
|
uvBuffer: createMappedBuffer(engine, uvs, BU.VERTEX),
|
|
204
|
-
idxBuffer: createMappedBuffer(engine, indices, BU.INDEX)
|
|
205
|
-
idxCount: 6
|
|
193
|
+
idxBuffer: createMappedBuffer(engine, indices, BU.INDEX)
|
|
206
194
|
};
|
|
207
195
|
}
|
|
208
|
-
function createBgMeshUBO(engine,
|
|
196
|
+
function createBgMeshUBO(engine, rootPosition, primaryColor) {
|
|
209
197
|
const data = new F32(BG_MESH_UNIFORM_SIZE / 4);
|
|
210
|
-
|
|
198
|
+
const eps = 2220446049250313e-31;
|
|
199
|
+
data[0] = data[15] = 1;
|
|
200
|
+
data[5] = data[10] = eps;
|
|
201
|
+
data[6] = -1;
|
|
202
|
+
data[9] = 1;
|
|
203
|
+
data[12] = rootPosition[0];
|
|
204
|
+
data[13] = rootPosition[1];
|
|
205
|
+
data[14] = rootPosition[2];
|
|
211
206
|
data[16] = primaryColor[0];
|
|
212
207
|
data[17] = primaryColor[1];
|
|
213
208
|
data[18] = primaryColor[2];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"background-ground.js","sources":["../../../../shaders/background.vertex.wgsl?raw","../../../../shaders/background.ground.fragment.wgsl?raw","../../../../src/material/pbr/background-ground.ts"],"sourcesContent":["export default \"// Background Ground Vertex Shader\\n// Matches BJS shd_15: DIFFUSE, OPACITYFRESNEL, PREMULTIPLYALPHA (no REFLECTION)\\n\\nstruct MeshUniforms {\\n world: mat4x4<f32>,\\n};\\n\\n@group(1) @binding(0) var<uniform> mesh: MeshUniforms;\\n\\nstruct VertexInput {\\n @location(0) position: vec3<f32>,\\n @location(1) normal: vec3<f32>,\\n @location(2) uv: vec2<f32>,\\n};\\n\\nstruct VertexOutput {\\n @builtin(position) clipPos: vec4<f32>,\\n @location(0) vPositionW: vec3<f32>,\\n @location(1) vNormalW: vec3<f32>,\\n @location(2) vUV: vec2<f32>,\\n};\\n\\n@vertex\\nfn main(input: VertexInput) -> VertexOutput {\\n var output: VertexOutput;\\n let finalWorld = mesh.world;\\n let worldPos4 = finalWorld * vec4<f32>(input.position, 1.0);\\n output.vPositionW = worldPos4.xyz;\\n output.clipPos = scene.viewProjection * worldPos4;\\n let normalWorld = mat3x3<f32>(finalWorld[0].xyz, finalWorld[1].xyz, finalWorld[2].xyz);\\n output.vNormalW = normalize(normalWorld * input.normal);\\n output.vUV = input.uv;\\n return output;\\n}\\n\"","export default \"// Background Ground Fragment Shader\\n// Matches BJS shd_16: DIFFUSE, OPACITYFRESNEL, PREMULTIPLYALPHA (no REFLECTION)\\n// Verified via Spector.GPU capture of BJS scene 1\\n\\nstruct MeshUniforms {\\n world: mat4x4<f32>,\\n primaryColor: vec3<f32>,\\n alpha: f32,\\n backgroundCenter: vec3<f32>,\\n _pad: f32,\\n};\\n@group(1) @binding(0) var<uniform> mesh: MeshUniforms;\\n\\n@group(1) @binding(1) var groundTexture: texture_2d<f32>;\\n@group(1) @binding(2) var groundSampler: sampler;\\n\\nstruct FragmentInput {\\n @location(0) vPositionW: vec3<f32>,\\n @location(1) vNormalW: vec3<f32>,\\n @location(2) vUV: vec2<f32>,\\n};\\n\\n@fragment\\nfn main(input: FragmentInput) -> @location(0) vec4<f32> {\\n let normalW = normalize(input.vNormalW);\\n\\n // Sample diffuse texture (BJS backgroundGround.png: white RGB, radial alpha gradient)\\n let diffuseMap = textureSample(groundTexture, groundSampler, input.vUV);\\n\\n // BJS: reflectionColor = vec4(1) (no REFLECTION define)\\n let diffuseColor = diffuseMap.rgb;\\n let colorBase = max(diffuseColor, vec3<f32>(0.0));\\n let mainColor = mesh.primaryColor;\\n let finalColor = colorBase * mainColor;\\n\\n // Alpha starts from material alpha, multiplied by texture alpha\\n var finalAlpha = mesh.alpha * diffuseMap.a;\\n\\n // OPACITYFRESNEL — BJS shd_16 lines 367-370\\n let viewAngleToFloor = dot(normalW, normalize(scene.vEyePosition.xyz - mesh.backgroundCenter));\\n const startAngle: f32 = 0.1;\\n let fadeFactor = clamp(viewAngleToFloor / startAngle, 0.0, 1.0);\\n finalAlpha *= fadeFactor * fadeFactor;\\n\\n // Image processing (preserves alpha)\\n var color = vec4<f32>(finalColor, finalAlpha);\\n if (scene.vImageInfos.w >= 0.0) {\\n color = applyImageProcessing(color);\\n }\\n\\n // PREMULTIPLYALPHA — BJS shd_16 line 373\\n color = vec4<f32>(color.rgb * color.a, color.a);\\n\\n // Dithering\\n color = vec4<f32>(color.rgb + vec3<f32>(dither(input.vPositionW.xy, 0.5)), color.a);\\n color = max(color, vec4<f32>(0.0));\\n\\n return color;\\n}\\n\"","/** Ground plane renderable — lazy-loaded only when a scene includes a ground.\n * Contains the ground material, mesh buffers, texture loading, and UBO creation.\n * Tree-shaken away from scenes that use `skipGround: true`. */\n\nimport { F32, U16, U8 } from \"../../engine/typed-arrays.js\";\nimport { TU, BU, SS } from \"../../engine/gpu-flags.js\";\nimport type { Mat4 } from \"../../math/types.js\";\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { Renderable } from \"../../render/renderable.js\";\nimport type { RenderTargetSignature } from \"../../engine/render-target.js\";\nimport { getBilinearSampler } from \"../../resource/samplers.js\";\nimport { createUniformBuffer } from \"../../resource/gpu-buffers.js\";\nimport { getSceneBindGroupLayout } from \"../../render/scene-helpers.js\";\nimport { targetSignatureKey } from \"../../engine/render-target.js\";\nimport groundVertSrc from \"../../../shaders/background.vertex.wgsl?raw\";\nimport groundFragSrc from \"../../../shaders/background.ground.fragment.wgsl?raw\";\nimport { createMappedBuffer } from \"../../resource/gpu-buffers.js\";\nimport { SCENE_UBO_WGSL } from \"../../shader/scene-uniforms.js\";\nimport { WGSL_DITHER, WGSL_NO_DITHER } from \"../../shader/wgsl-helpers.js\";\n\n// ── Ground-frag-only WGSL helpers (kept here so scenes that don't load the ground\n// don't pay for the image-processing helper in the shared wgsl-helpers chunk). ──\n\n/** Image processing: exposure → Reinhard tonemap → gamma → contrast. */\nconst WGSL_IMAGE_PROCESSING = `\nfn applyImageProcessing(result: vec4<f32>) -> vec4<f32> {\nvar rgb = result.rgb;\nrgb *= scene.vImageInfos.x;\nconst tonemappingCalibration: f32 = 1.590579;\nrgb = 1.0 - exp2(-tonemappingCalibration * rgb);\nrgb = pow(rgb, vec3<f32>(1.0 / 2.2));\nrgb = clamp(rgb, vec3<f32>(0.0), vec3<f32>(1.0));\nlet highContrast = rgb * rgb * (3.0 - 2.0 * rgb);\nif (scene.vImageInfos.y < 1.0) {\nrgb = mix(vec3<f32>(0.5), rgb, scene.vImageInfos.y);\n} else {\nrgb = mix(rgb, highContrast, scene.vImageInfos.y - 1.0);\n}\nrgb = max(rgb, vec3<f32>(0.0));\nreturn vec4<f32>(rgb, result.a);\n}\n`;\n\nconst BG_MESH_UNIFORM_SIZE = 96; // mat4x4 + primaryColor vec3 + alpha + backgroundCenter vec3 + pad\n\n/** Build the ground renderable for a PBR environment scene. */\nexport async function buildGroundRenderable(\n engine: EngineContext,\n groundSize: number,\n rootPosition: [number, number, number],\n primaryColor: [number, number, number],\n groundTextureUrl?: string,\n groundImagePromise?: Promise<ImageBitmap>,\n enableNoise = true\n): Promise<Renderable> {\n const fragCode = SCENE_UBO_WGSL + WGSL_IMAGE_PROCESSING + (enableNoise ? WGSL_DITHER : WGSL_NO_DITHER) + groundFragSrc;\n const gndMat = createGroundMaterial(enableNoise, fragCode);\n\n // Ground world: rotated 90° X (XY→XZ), translated to rootPosition\n // Column-major for WGSL: ground quad in XY plane, normal +Z → world +Y\n // Offset Y by -0.01 to prevent z-fighting with scene floor geometry.\n const eps = 2.220446049250313e-16;\n const groundWorld = new F32(16);\n groundWorld[0] = 1;\n groundWorld[5] = eps;\n groundWorld[6] = -1;\n groundWorld[9] = 1;\n groundWorld[10] = eps;\n groundWorld[12] = rootPosition[0];\n groundWorld[13] = rootPosition[1];\n groundWorld[14] = rootPosition[2];\n groundWorld[15] = 1;\n\n const gndBufs = createGroundBuffers(engine, groundSize);\n const gndUBO = createBgMeshUBO(engine, groundWorld as unknown as Mat4, primaryColor);\n\n const groundTex = await loadGroundTexture(engine, groundTextureUrl, groundImagePromise);\n const groundTexView = groundTex.createView();\n const groundSamp = getBilinearSampler(engine);\n const gndBG = gndMat.createBindGroup(engine, gndUBO, groundTexView, groundSamp);\n\n const r: Renderable = {\n order: 200, // ground renders last (transparent)\n isTransparent: true,\n bind(eng, sig) {\n return {\n renderable: r,\n pipeline: gndMat.getPipeline(eng as EngineContext, sig),\n draw(pass) {\n pass.setBindGroup(1, gndBG);\n pass.setVertexBuffer(0, gndBufs.posBuffer);\n pass.setVertexBuffer(1, gndBufs.normBuffer);\n pass.setVertexBuffer(2, gndBufs.uvBuffer);\n pass.setIndexBuffer(gndBufs.idxBuffer, \"uint16\");\n pass.drawIndexed(gndBufs.idxCount);\n return 1;\n },\n };\n },\n };\n return r;\n}\n\n// ─── Ground Material ────────────────────────────────────────────────────────\n\ninterface GroundMaterial {\n getPipeline(engine: EngineContext, sig: RenderTargetSignature): GPURenderPipeline;\n createBindGroup(engine: EngineContext, meshUBO: GPUBuffer, groundTextureView: GPUTextureView, groundSampler: GPUSampler): GPUBindGroup;\n}\n\n/** Module-global pipeline cache — keyed by noise mode + full target signature (color/depth/samples/flipY).\n * All ground renderables share this cache. */\nconst _gndPipelines = new Map<string, GPURenderPipeline>();\nlet _gndLayout: GPUBindGroupLayout | null = null;\nlet _gndCachedDevice: GPUDevice | null = null;\n\nfunction createGroundMaterial(enableNoise: boolean, fragCode: string): GroundMaterial {\n function getLayout(engine: EngineContext): GPUBindGroupLayout {\n const device = engine._device;\n if (_gndLayout && _gndCachedDevice === device) {\n return _gndLayout;\n }\n _gndLayout = device.createBindGroupLayout({\n label: \"ground-material\",\n entries: [\n { binding: 0, visibility: SS.VERTEX | SS.FRAGMENT, buffer: { type: \"uniform\" } },\n { binding: 1, visibility: SS.FRAGMENT, texture: { sampleType: \"float\", viewDimension: \"2d\" } },\n { binding: 2, visibility: SS.FRAGMENT, sampler: { type: \"filtering\" } },\n ],\n });\n _gndCachedDevice = device;\n return _gndLayout;\n }\n\n return {\n getPipeline(engine, sig) {\n const device = engine._device;\n if (_gndCachedDevice !== device) {\n _gndPipelines.clear();\n _gndLayout = null;\n _gndCachedDevice = device;\n }\n const key = `${+enableNoise}|${targetSignatureKey(sig)}`;\n const cached = _gndPipelines.get(key);\n if (cached) {\n return cached;\n }\n const vertModule = device.createShaderModule({ code: SCENE_UBO_WGSL + groundVertSrc, label: \"ground-vert\" });\n const fragModule = device.createShaderModule({ code: fragCode, label: \"ground-frag\" });\n\n // Matches BJS rp_8: premultiplied alpha blend, depthWrite=false\n const pipeline = device.createRenderPipeline({\n label: \"ground-pipeline\",\n layout: device.createPipelineLayout({ bindGroupLayouts: [getSceneBindGroupLayout(engine), getLayout(engine)] }),\n vertex: {\n module: vertModule,\n entryPoint: \"main\",\n buffers: [\n { arrayStride: 12, attributes: [{ shaderLocation: 0, offset: 0, format: \"float32x3\" as GPUVertexFormat }] },\n { arrayStride: 12, attributes: [{ shaderLocation: 1, offset: 0, format: \"float32x3\" as GPUVertexFormat }] },\n { arrayStride: 8, attributes: [{ shaderLocation: 2, offset: 0, format: \"float32x2\" as GPUVertexFormat }] },\n ],\n },\n fragment: {\n module: fragModule,\n entryPoint: \"main\",\n targets: [\n {\n format: sig._colorFormat!,\n blend: {\n color: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n },\n },\n ],\n },\n depthStencil: {\n format: sig._depthStencilFormat ?? \"depth24plus-stencil8\",\n depthCompare: sig._depthCompare ?? \"greater-equal\",\n depthWriteEnabled: false,\n },\n multisample: { count: sig._sampleCount },\n primitive: { topology: \"triangle-list\", cullMode: \"back\", frontFace: \"ccw\" },\n });\n _gndPipelines.set(key, pipeline);\n return pipeline;\n },\n\n createBindGroup(engine, meshUBO, groundTextureView, groundSampler) {\n const device = engine._device;\n return device.createBindGroup({\n layout: getLayout(engine),\n entries: [\n { binding: 0, resource: { buffer: meshUBO } },\n { binding: 1, resource: groundTextureView },\n { binding: 2, resource: groundSampler },\n ],\n });\n },\n };\n}\n\n// ─── Ground Mesh Data ───────────────────────────────────────────────────────\n\n/** Ground quad (4 verts, 6 indices — matches BJS CreatePlane with BACKSIDE).\n * XY plane, normals +Z (become +Y after world rotation). */\nfunction createGroundBuffers(\n engine: EngineContext,\n groundSize: number\n): {\n posBuffer: GPUBuffer;\n normBuffer: GPUBuffer;\n uvBuffer: GPUBuffer;\n idxBuffer: GPUBuffer;\n idxCount: number;\n} {\n const h = groundSize / 2;\n // prettier-ignore\n const positions = new F32([\n -h, -h, 0,\n h, -h, 0,\n h, h, 0,\n -h, h, 0,\n ]);\n // prettier-ignore\n const normals = new F32([\n 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,\n ]);\n // prettier-ignore\n const uvs = new F32([\n 0, 0, 1, 0, 1, 1, 0, 1,\n ]);\n // BACKSIDE winding\n // prettier-ignore\n const indices = new U16([0, 2, 1, 0, 3, 2]);\n\n return {\n posBuffer: createMappedBuffer(engine, positions, BU.VERTEX),\n normBuffer: createMappedBuffer(engine, normals, BU.VERTEX),\n uvBuffer: createMappedBuffer(engine, uvs, BU.VERTEX),\n idxBuffer: createMappedBuffer(engine, indices, BU.INDEX),\n idxCount: 6,\n };\n}\n\n// ─── Ground UBO ─────────────────────────────────────────────────────────────\n\nfunction createBgMeshUBO(engine: EngineContext, world: Mat4, primaryColor: [number, number, number]): GPUBuffer {\n const data = new F32(BG_MESH_UNIFORM_SIZE / 4);\n data.set(world, 0); // offset 0: world mat4x4\n data[16] = primaryColor[0]; // offset 64: primaryColor.r\n data[17] = primaryColor[1]; // offset 68: primaryColor.g\n data[18] = primaryColor[2]; // offset 72: primaryColor.b\n data[19] = 0.9; // offset 76: alpha (BJS default groundOpacity)\n data[20] = 0;\n data[21] = 0;\n data[22] = 0; // offset 80: backgroundCenter\n return createUniformBuffer(engine, data);\n}\n\n// ─── Ground Texture ─────────────────────────────────────────────────────────\n\n/** Load a ground diffuse texture from URL and upload to GPU.\n * Falls back to a 1×1 white pixel if no URL provided. */\nasync function loadGroundTexture(engine: EngineContext, url?: string, preloadedImage?: Promise<ImageBitmap>): Promise<GPUTexture> {\n const device = engine._device;\n if (!url) {\n const tex = device.createTexture({\n size: [1, 1],\n format: \"rgba8unorm\",\n usage: TU.TEXTURE_BINDING | TU.COPY_DST,\n });\n device.queue.writeTexture({ texture: tex }, new U8([255, 255, 255, 255]), { bytesPerRow: 4 }, [1, 1]);\n return tex;\n }\n // Use pre-fetched image if available (started early in loadEnvironment)\n const bmp = preloadedImage\n ? await preloadedImage\n : await fetch(url)\n .then((r) => r.blob())\n .then((b) => createImageBitmap(b, { premultiplyAlpha: \"none\" }));\n const tex = device.createTexture({\n size: [bmp.width, bmp.height],\n format: \"rgba8unorm\",\n usage: TU.TEXTURE_BINDING | TU.COPY_DST | TU.RENDER_ATTACHMENT,\n });\n device.queue.copyExternalImageToTexture({ source: bmp }, { texture: tex }, [bmp.width, bmp.height]);\n bmp.close();\n return tex;\n}\n"],"names":["tex"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"background-ground.js","sources":["../../../../shaders/background.vertex.wgsl?raw","../../../../shaders/background.ground.fragment.wgsl?raw","../../../../src/material/pbr/background-ground.ts"],"sourcesContent":["export default \"// Background Ground Vertex Shader\\n// Matches BJS shd_15: DIFFUSE, OPACITYFRESNEL, PREMULTIPLYALPHA (no REFLECTION)\\n\\nstruct MeshUniforms {\\n world: mat4x4<f32>,\\n};\\n\\n@group(1) @binding(0) var<uniform> mesh: MeshUniforms;\\n\\nstruct VertexInput {\\n @location(0) position: vec3<f32>,\\n @location(1) normal: vec3<f32>,\\n @location(2) uv: vec2<f32>,\\n};\\n\\nstruct VertexOutput {\\n @builtin(position) clipPos: vec4<f32>,\\n @location(0) vPositionW: vec3<f32>,\\n @location(1) vNormalW: vec3<f32>,\\n @location(2) vUV: vec2<f32>,\\n};\\n\\n@vertex\\nfn main(input: VertexInput) -> VertexOutput {\\n var output: VertexOutput;\\n let finalWorld = mesh.world;\\n let worldPos4 = finalWorld * vec4<f32>(input.position, 1.0);\\n output.vPositionW = worldPos4.xyz;\\n output.clipPos = scene.viewProjection * worldPos4;\\n let normalWorld = mat3x3<f32>(finalWorld[0].xyz, finalWorld[1].xyz, finalWorld[2].xyz);\\n output.vNormalW = normalize(normalWorld * input.normal);\\n output.vUV = input.uv;\\n return output;\\n}\\n\"","export default \"// Background Ground Fragment Shader\\n// Matches BJS shd_16: DIFFUSE, OPACITYFRESNEL, PREMULTIPLYALPHA (no REFLECTION)\\n// Verified via Spector.GPU capture of BJS scene 1\\n\\nstruct MeshUniforms {\\n world: mat4x4<f32>,\\n primaryColor: vec3<f32>,\\n alpha: f32,\\n backgroundCenter: vec3<f32>,\\n _pad: f32,\\n};\\n@group(1) @binding(0) var<uniform> mesh: MeshUniforms;\\n\\n@group(1) @binding(1) var groundTexture: texture_2d<f32>;\\n@group(1) @binding(2) var groundSampler: sampler;\\n\\nstruct FragmentInput {\\n @location(0) vPositionW: vec3<f32>,\\n @location(1) vNormalW: vec3<f32>,\\n @location(2) vUV: vec2<f32>,\\n};\\n\\n@fragment\\nfn main(input: FragmentInput) -> @location(0) vec4<f32> {\\n let normalW = normalize(input.vNormalW);\\n\\n // Sample diffuse texture (BJS backgroundGround.png: white RGB, radial alpha gradient)\\n let diffuseMap = textureSample(groundTexture, groundSampler, input.vUV);\\n\\n // BJS: reflectionColor = vec4(1) (no REFLECTION define)\\n let diffuseColor = diffuseMap.rgb;\\n let colorBase = max(diffuseColor, vec3<f32>(0.0));\\n let mainColor = mesh.primaryColor;\\n let finalColor = colorBase * mainColor;\\n\\n // Alpha starts from material alpha, multiplied by texture alpha\\n var finalAlpha = mesh.alpha * diffuseMap.a;\\n\\n // OPACITYFRESNEL — BJS shd_16 lines 367-370\\n let viewAngleToFloor = dot(normalW, normalize(scene.vEyePosition.xyz - mesh.backgroundCenter));\\n const startAngle: f32 = 0.1;\\n let fadeFactor = clamp(viewAngleToFloor / startAngle, 0.0, 1.0);\\n finalAlpha *= fadeFactor * fadeFactor;\\n\\n // Image processing (preserves alpha)\\n var color = vec4<f32>(finalColor, finalAlpha);\\n if (scene.vImageInfos.w >= 0.0) {\\n color = applyImageProcessing(color);\\n }\\n\\n // PREMULTIPLYALPHA — BJS shd_16 line 373\\n color = vec4<f32>(color.rgb * color.a, color.a);\\n\\n // Dithering\\n color = vec4<f32>(color.rgb + vec3<f32>(dither(input.vPositionW.xy, 0.5)), color.a);\\n color = max(color, vec4<f32>(0.0));\\n\\n return color;\\n}\\n\"","/** Ground plane renderable — lazy-loaded only when a scene includes a ground.\n * Contains the ground material, mesh buffers, texture loading, and UBO creation.\n * Tree-shaken away from scenes that use `skipGround: true`. */\n\nimport { F32, U16, U8 } from \"../../engine/typed-arrays.js\";\nimport { TU, BU, SS } from \"../../engine/gpu-flags.js\";\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { Renderable } from \"../../render/renderable.js\";\nimport type { RenderTargetSignature } from \"../../engine/render-target.js\";\nimport { getBilinearSampler } from \"../../resource/samplers.js\";\nimport { createUniformBuffer } from \"../../resource/gpu-buffers.js\";\nimport { getSceneBindGroupLayout } from \"../../render/scene-helpers.js\";\nimport { targetSignatureKey } from \"../../engine/render-target.js\";\nimport groundVertSrc from \"../../../shaders/background.vertex.wgsl?raw\";\nimport groundFragSrc from \"../../../shaders/background.ground.fragment.wgsl?raw\";\nimport { createMappedBuffer } from \"../../resource/gpu-buffers.js\";\nimport { SCENE_UBO_WGSL } from \"../../shader/scene-uniforms.js\";\nimport { WGSL_DITHER, WGSL_NO_DITHER } from \"../../shader/wgsl-helpers.js\";\n\n// ── Ground-frag-only WGSL helpers (kept here so scenes that don't load the ground\n// don't pay for the image-processing helper in the shared wgsl-helpers chunk). ──\n\n/** Image processing: exposure → Reinhard tonemap → gamma → contrast. */\nconst WGSL_IMAGE_PROCESSING = `\nfn applyImageProcessing(result: vec4<f32>) -> vec4<f32> {\nvar rgb = result.rgb;\nrgb *= scene.vImageInfos.x;\nconst tonemappingCalibration: f32 = 1.590579;\nrgb = 1.0 - exp2(-tonemappingCalibration * rgb);\nrgb = pow(rgb, vec3<f32>(1.0 / 2.2));\nrgb = clamp(rgb, vec3<f32>(0.0), vec3<f32>(1.0));\nlet highContrast = rgb * rgb * (3.0 - 2.0 * rgb);\nif (scene.vImageInfos.y < 1.0) {\nrgb = mix(vec3<f32>(0.5), rgb, scene.vImageInfos.y);\n} else {\nrgb = mix(rgb, highContrast, scene.vImageInfos.y - 1.0);\n}\nrgb = max(rgb, vec3<f32>(0.0));\nreturn vec4<f32>(rgb, result.a);\n}\n`;\n\nconst BG_MESH_UNIFORM_SIZE = 96; // mat4x4 + primaryColor vec3 + alpha + backgroundCenter vec3 + pad\n\n/** Build the ground renderable for a PBR environment scene. */\nexport async function buildGroundRenderable(\n engine: EngineContext,\n groundSize: number,\n rootPosition: [number, number, number],\n primaryColor: [number, number, number],\n groundTextureUrl?: string,\n groundImagePromise?: Promise<ImageBitmap>,\n enableNoise = true\n): Promise<Renderable> {\n const fragCode = SCENE_UBO_WGSL + WGSL_IMAGE_PROCESSING + (enableNoise ? WGSL_DITHER : WGSL_NO_DITHER) + groundFragSrc;\n const gndMat = createGroundMaterial(enableNoise, fragCode);\n\n const gndBufs = createGroundBuffers(engine, groundSize);\n const gndUBO = createBgMeshUBO(engine, rootPosition, primaryColor);\n\n const groundTex = await loadGroundTexture(engine, groundTextureUrl, groundImagePromise);\n const groundTexView = groundTex.createView();\n const groundSamp = getBilinearSampler(engine);\n const gndBG = gndMat.createBindGroup(engine, gndUBO, groundTexView, groundSamp);\n\n const r: Renderable = {\n order: 200, // ground renders last (transparent)\n isTransparent: true,\n bind(eng, sig) {\n return {\n renderable: r,\n pipeline: gndMat.getPipeline(eng as EngineContext, sig),\n draw(pass) {\n pass.setBindGroup(1, gndBG);\n pass.setVertexBuffer(0, gndBufs.posBuffer);\n pass.setVertexBuffer(1, gndBufs.normBuffer);\n pass.setVertexBuffer(2, gndBufs.uvBuffer);\n pass.setIndexBuffer(gndBufs.idxBuffer, \"uint16\");\n pass.drawIndexed(6);\n return 1;\n },\n };\n },\n };\n return r;\n}\n\n// ─── Ground Material ────────────────────────────────────────────────────────\n\ninterface GroundMaterial {\n getPipeline(engine: EngineContext, sig: RenderTargetSignature): GPURenderPipeline;\n createBindGroup(engine: EngineContext, meshUBO: GPUBuffer, groundTextureView: GPUTextureView, groundSampler: GPUSampler): GPUBindGroup;\n}\n\n/** Module-global pipeline cache — keyed by noise mode + full target signature (color/depth/samples/flipY).\n * All ground renderables share this cache. */\nconst _gndPipelines = new Map<string, GPURenderPipeline>();\nlet _gndLayout: GPUBindGroupLayout | null = null;\nlet _gndCachedDevice: GPUDevice | null = null;\n\nfunction createGroundMaterial(enableNoise: boolean, fragCode: string): GroundMaterial {\n function getLayout(engine: EngineContext): GPUBindGroupLayout {\n const device = engine._device;\n if (_gndLayout && _gndCachedDevice === device) {\n return _gndLayout;\n }\n _gndLayout = device.createBindGroupLayout({\n label: \"ground-material\",\n entries: [\n { binding: 0, visibility: SS.VERTEX | SS.FRAGMENT, buffer: { type: \"uniform\" } },\n { binding: 1, visibility: SS.FRAGMENT, texture: { sampleType: \"float\", viewDimension: \"2d\" } },\n { binding: 2, visibility: SS.FRAGMENT, sampler: { type: \"filtering\" } },\n ],\n });\n _gndCachedDevice = device;\n return _gndLayout;\n }\n\n return {\n getPipeline(engine, sig) {\n const device = engine._device;\n if (_gndCachedDevice !== device) {\n _gndPipelines.clear();\n _gndLayout = null;\n _gndCachedDevice = device;\n }\n const key = `${+enableNoise}|${targetSignatureKey(sig)}`;\n const cached = _gndPipelines.get(key);\n if (cached) {\n return cached;\n }\n const vertModule = device.createShaderModule({ code: SCENE_UBO_WGSL + groundVertSrc, label: \"ground-vert\" });\n const fragModule = device.createShaderModule({ code: fragCode, label: \"ground-frag\" });\n\n // Matches BJS rp_8: premultiplied alpha blend, depthWrite=false\n const pipeline = device.createRenderPipeline({\n label: \"ground-pipeline\",\n layout: device.createPipelineLayout({ bindGroupLayouts: [getSceneBindGroupLayout(engine), getLayout(engine)] }),\n vertex: {\n module: vertModule,\n entryPoint: \"main\",\n buffers: [\n { arrayStride: 12, attributes: [{ shaderLocation: 0, offset: 0, format: \"float32x3\" as GPUVertexFormat }] },\n { arrayStride: 12, attributes: [{ shaderLocation: 1, offset: 0, format: \"float32x3\" as GPUVertexFormat }] },\n { arrayStride: 8, attributes: [{ shaderLocation: 2, offset: 0, format: \"float32x2\" as GPUVertexFormat }] },\n ],\n },\n fragment: {\n module: fragModule,\n entryPoint: \"main\",\n targets: [\n {\n format: sig._colorFormat!,\n blend: {\n color: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n },\n },\n ],\n },\n depthStencil: {\n format: sig._depthStencilFormat ?? \"depth24plus-stencil8\",\n depthCompare: sig._depthCompare ?? \"greater-equal\",\n depthWriteEnabled: false,\n },\n multisample: { count: sig._sampleCount },\n primitive: { topology: \"triangle-list\", cullMode: \"back\", frontFace: \"ccw\" },\n });\n _gndPipelines.set(key, pipeline);\n return pipeline;\n },\n\n createBindGroup(engine, meshUBO, groundTextureView, groundSampler) {\n const device = engine._device;\n return device.createBindGroup({\n layout: getLayout(engine),\n entries: [\n { binding: 0, resource: { buffer: meshUBO } },\n { binding: 1, resource: groundTextureView },\n { binding: 2, resource: groundSampler },\n ],\n });\n },\n };\n}\n\n// ─── Ground Mesh Data ───────────────────────────────────────────────────────\n\n/** Ground quad (4 verts, 6 indices — matches BJS CreatePlane with BACKSIDE).\n * XY plane, normals +Z (become +Y after world rotation). */\nfunction createGroundBuffers(\n engine: EngineContext,\n groundSize: number\n): {\n posBuffer: GPUBuffer;\n normBuffer: GPUBuffer;\n uvBuffer: GPUBuffer;\n idxBuffer: GPUBuffer;\n} {\n const h = groundSize / 2;\n // prettier-ignore\n const positions = new F32([\n -h, -h, 0,\n h, -h, 0,\n h, h, 0,\n -h, h, 0,\n ]);\n // prettier-ignore\n const normals = new F32([\n 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,\n ]);\n // prettier-ignore\n const uvs = new F32([\n 0, 0, 1, 0, 1, 1, 0, 1,\n ]);\n // BACKSIDE winding\n // prettier-ignore\n const indices = new U16([0, 2, 1, 0, 3, 2]);\n\n return {\n posBuffer: createMappedBuffer(engine, positions, BU.VERTEX),\n normBuffer: createMappedBuffer(engine, normals, BU.VERTEX),\n uvBuffer: createMappedBuffer(engine, uvs, BU.VERTEX),\n idxBuffer: createMappedBuffer(engine, indices, BU.INDEX),\n };\n}\n\n// ─── Ground UBO ─────────────────────────────────────────────────────────────\n\nfunction createBgMeshUBO(engine: EngineContext, rootPosition: [number, number, number], primaryColor: [number, number, number]): GPUBuffer {\n const data = new F32(BG_MESH_UNIFORM_SIZE / 4);\n // Ground world: rotate XY to XZ, then translate to the scene root.\n const eps = 2.220446049250313e-16;\n data[0] = data[15] = 1;\n data[5] = data[10] = eps;\n data[6] = -1;\n data[9] = 1;\n data[12] = rootPosition[0];\n data[13] = rootPosition[1];\n data[14] = rootPosition[2];\n data[16] = primaryColor[0]; // offset 64: primaryColor.r\n data[17] = primaryColor[1]; // offset 68: primaryColor.g\n data[18] = primaryColor[2]; // offset 72: primaryColor.b\n data[19] = 0.9; // offset 76: alpha (BJS default groundOpacity)\n data[20] = 0;\n data[21] = 0;\n data[22] = 0; // offset 80: backgroundCenter\n return createUniformBuffer(engine, data);\n}\n\n// ─── Ground Texture ─────────────────────────────────────────────────────────\n\n/** Load a ground diffuse texture from URL and upload to GPU.\n * Falls back to a 1×1 white pixel if no URL provided. */\nasync function loadGroundTexture(engine: EngineContext, url?: string, preloadedImage?: Promise<ImageBitmap>): Promise<GPUTexture> {\n const device = engine._device;\n if (!url) {\n const tex = device.createTexture({\n size: [1, 1],\n format: \"rgba8unorm\",\n usage: TU.TEXTURE_BINDING | TU.COPY_DST,\n });\n device.queue.writeTexture({ texture: tex }, new U8([255, 255, 255, 255]), { bytesPerRow: 4 }, [1, 1]);\n return tex;\n }\n // Use pre-fetched image if available (started early in loadEnvironment)\n const bmp = preloadedImage\n ? await preloadedImage\n : await fetch(url)\n .then((r) => r.blob())\n .then((b) => createImageBitmap(b, { premultiplyAlpha: \"none\" }));\n const tex = device.createTexture({\n size: [bmp.width, bmp.height],\n format: \"rgba8unorm\",\n usage: TU.TEXTURE_BINDING | TU.COPY_DST | TU.RENDER_ATTACHMENT,\n });\n device.queue.copyExternalImageToTexture({ source: bmp }, { texture: tex }, [bmp.width, bmp.height]);\n bmp.close();\n return tex;\n}\n"],"names":["tex"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { U16, F32 } from '../../engine/typed-arrays.js';
|
|
2
2
|
import { BU } from '../../engine/gpu-flags.js';
|
|
3
3
|
import { createCubemapSkyboxMaterial } from './cubemap-skybox-material.js';
|
|
4
4
|
import { s as skyboxVertSrc } from '../../_chunks/skybox.vertex-Ban7q6IM.js';
|
|
@@ -10,141 +10,80 @@ const skyboxHdrFragSrc = "struct g{world:mat4x4<f32>,primaryColor:vec3<f32>,_pad
|
|
|
10
10
|
const SKY_HDR_UNIFORM_SIZE = 112;
|
|
11
11
|
function createSkyboxBuffers(engine, S) {
|
|
12
12
|
const positions = new F32([
|
|
13
|
-
S,
|
|
14
|
-
-S,
|
|
15
|
-
S,
|
|
16
|
-
-S,
|
|
17
|
-
-S,
|
|
18
|
-
S,
|
|
19
|
-
-S,
|
|
20
|
-
S,
|
|
21
|
-
S,
|
|
22
|
-
S,
|
|
23
|
-
S,
|
|
24
|
-
S,
|
|
25
|
-
S,
|
|
26
|
-
S,
|
|
27
|
-
-S,
|
|
28
|
-
-S,
|
|
29
|
-
S,
|
|
30
|
-
-S,
|
|
31
|
-
-S,
|
|
32
13
|
-S,
|
|
33
14
|
-S,
|
|
34
|
-
S,
|
|
35
|
-
-S,
|
|
36
15
|
-S,
|
|
37
16
|
S,
|
|
38
|
-
S,
|
|
39
17
|
-S,
|
|
40
|
-
S,
|
|
41
18
|
-S,
|
|
42
19
|
-S,
|
|
43
20
|
S,
|
|
44
21
|
-S,
|
|
45
22
|
S,
|
|
46
23
|
S,
|
|
47
|
-
S,
|
|
48
|
-
S,
|
|
49
24
|
-S,
|
|
50
|
-
S,
|
|
51
|
-
S,
|
|
52
25
|
-S,
|
|
53
26
|
-S,
|
|
54
27
|
S,
|
|
55
|
-
-S,
|
|
56
|
-
-S,
|
|
57
|
-
-S,
|
|
58
|
-
-S,
|
|
59
28
|
S,
|
|
60
29
|
-S,
|
|
61
|
-
-S,
|
|
62
|
-
S,
|
|
63
|
-
S,
|
|
64
|
-
-S,
|
|
65
|
-
S,
|
|
66
|
-
-S,
|
|
67
|
-
S,
|
|
68
30
|
S,
|
|
69
31
|
-S,
|
|
70
32
|
S,
|
|
71
33
|
S,
|
|
72
34
|
S,
|
|
73
35
|
S,
|
|
74
|
-
-S,
|
|
75
|
-
S,
|
|
76
|
-
S,
|
|
77
|
-
-S,
|
|
78
|
-
-S,
|
|
79
|
-
-S,
|
|
80
|
-
-S,
|
|
81
|
-
-S,
|
|
82
|
-
-S,
|
|
83
|
-
-S,
|
|
84
36
|
S
|
|
85
37
|
]);
|
|
86
38
|
const indices = new U16([
|
|
39
|
+
6,
|
|
40
|
+
4,
|
|
41
|
+
5,
|
|
42
|
+
7,
|
|
43
|
+
6,
|
|
44
|
+
5,
|
|
45
|
+
0,
|
|
87
46
|
2,
|
|
47
|
+
3,
|
|
88
48
|
1,
|
|
89
49
|
0,
|
|
90
50
|
3,
|
|
51
|
+
5,
|
|
52
|
+
1,
|
|
53
|
+
3,
|
|
54
|
+
7,
|
|
55
|
+
5,
|
|
56
|
+
3,
|
|
57
|
+
0,
|
|
58
|
+
4,
|
|
59
|
+
6,
|
|
91
60
|
2,
|
|
92
61
|
0,
|
|
93
62
|
6,
|
|
94
|
-
|
|
95
|
-
|
|
63
|
+
3,
|
|
64
|
+
2,
|
|
65
|
+
6,
|
|
96
66
|
7,
|
|
67
|
+
3,
|
|
97
68
|
6,
|
|
69
|
+
0,
|
|
70
|
+
1,
|
|
71
|
+
5,
|
|
98
72
|
4,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
8,
|
|
102
|
-
11,
|
|
103
|
-
10,
|
|
104
|
-
8,
|
|
105
|
-
14,
|
|
106
|
-
13,
|
|
107
|
-
12,
|
|
108
|
-
15,
|
|
109
|
-
14,
|
|
110
|
-
12,
|
|
111
|
-
18,
|
|
112
|
-
17,
|
|
113
|
-
16,
|
|
114
|
-
19,
|
|
115
|
-
18,
|
|
116
|
-
16,
|
|
117
|
-
22,
|
|
118
|
-
21,
|
|
119
|
-
20,
|
|
120
|
-
23,
|
|
121
|
-
22,
|
|
122
|
-
20
|
|
73
|
+
0,
|
|
74
|
+
5
|
|
123
75
|
]);
|
|
124
76
|
return {
|
|
125
77
|
posBuffer: createMappedBuffer(engine, positions, BU.VERTEX),
|
|
126
|
-
idxBuffer: createMappedBuffer(engine, indices, BU.INDEX)
|
|
127
|
-
idxCount: 36
|
|
78
|
+
idxBuffer: createMappedBuffer(engine, indices, BU.INDEX)
|
|
128
79
|
};
|
|
129
80
|
}
|
|
130
|
-
function buildSkyboxWorldMatrix(rootPosition) {
|
|
131
|
-
const world = new F32(16);
|
|
132
|
-
world[0] = 1;
|
|
133
|
-
world[5] = 1;
|
|
134
|
-
world[10] = 1;
|
|
135
|
-
world[15] = 1;
|
|
136
|
-
world[12] = rootPosition[0];
|
|
137
|
-
world[13] = rootPosition[1];
|
|
138
|
-
world[14] = rootPosition[2];
|
|
139
|
-
return world;
|
|
140
|
-
}
|
|
141
81
|
function buildHdrSkyboxRenderable(scene, envTextures, skyHalfSize, rootPosition, primaryColor) {
|
|
142
82
|
const engine = scene.surface.engine;
|
|
143
|
-
const skyboxWorld = buildSkyboxWorldMatrix(rootPosition);
|
|
144
83
|
const cc = scene.clearColor;
|
|
145
84
|
const skyBufs = createSkyboxBuffers(engine, skyHalfSize);
|
|
146
85
|
const mat = createCubemapSkyboxMaterial("skybox-hdr", SCENE_UBO_WGSL + skyboxVertSrc, skyboxHdrFragSrc);
|
|
147
|
-
const ubo = createSkyHdrMeshUBO(engine,
|
|
86
|
+
const ubo = createSkyHdrMeshUBO(engine, rootPosition, primaryColor, [cc.r, cc.g, cc.b], scene.imageProcessing.exposure, scene.imageProcessing.contrast);
|
|
148
87
|
const bindGroup = mat.createBindGroup(engine, ubo, envTextures.specularCubeView, envTextures.cubeSampler);
|
|
149
88
|
const r = {
|
|
150
89
|
order: 0,
|
|
@@ -157,7 +96,7 @@ function buildHdrSkyboxRenderable(scene, envTextures, skyHalfSize, rootPosition,
|
|
|
157
96
|
pass.setBindGroup(1, bindGroup);
|
|
158
97
|
pass.setVertexBuffer(0, skyBufs.posBuffer);
|
|
159
98
|
pass.setIndexBuffer(skyBufs.idxBuffer, "uint16");
|
|
160
|
-
pass.drawIndexed(
|
|
99
|
+
pass.drawIndexed(36);
|
|
161
100
|
return 1;
|
|
162
101
|
}
|
|
163
102
|
};
|
|
@@ -165,9 +104,12 @@ function buildHdrSkyboxRenderable(scene, envTextures, skyHalfSize, rootPosition,
|
|
|
165
104
|
};
|
|
166
105
|
return r;
|
|
167
106
|
}
|
|
168
|
-
function createSkyHdrMeshUBO(engine,
|
|
107
|
+
function createSkyHdrMeshUBO(engine, rootPosition, primaryColor, skyOutputColor, exposure, contrast) {
|
|
169
108
|
const data = new F32(SKY_HDR_UNIFORM_SIZE / 4);
|
|
170
|
-
data
|
|
109
|
+
data[0] = data[5] = data[10] = data[15] = 1;
|
|
110
|
+
data[12] = rootPosition[0];
|
|
111
|
+
data[13] = rootPosition[1];
|
|
112
|
+
data[14] = rootPosition[2];
|
|
171
113
|
data[16] = primaryColor[0];
|
|
172
114
|
data[17] = primaryColor[1];
|
|
173
115
|
data[18] = primaryColor[2];
|