@woosh/meep-engine 3.61.0 → 3.61.2
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/package.json +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +4 -0
- package/src/engine/graphics/ecs/decal/v2/Decal.d.ts +46 -2
- package/src/engine/graphics/ecs/decal/v2/Decal.d.ts.map +1 -1
- package/src/engine/graphics/ecs/decal/v2/Decal.js +74 -5
- package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.d.ts.map +1 -1
- package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.js +13 -1
- package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.d.ts +9 -0
- package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.d.ts.map +1 -0
- package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.js +37 -0
- package/src/engine/graphics3/DecalSystem.d.ts.map +1 -1
- package/src/engine/graphics3/DecalSystem.js +462 -447
- package/src/engine/graphics3/decal/DECAL_GPU_RECORD.d.ts +14 -0
- package/src/engine/graphics3/decal/DECAL_GPU_RECORD.d.ts.map +1 -1
- package/src/engine/graphics3/decal/DECAL_GPU_RECORD.js +53 -13
- package/src/engine/graphics3/decal/chunk_decal_record.d.ts +6 -1
- package/src/engine/graphics3/decal/chunk_decal_record.d.ts.map +1 -1
- package/src/engine/graphics3/decal/chunk_decal_record.js +28 -9
- package/src/engine/graphics3/decal/decal_gpu_records.d.ts +2 -1
- package/src/engine/graphics3/decal/decal_gpu_records.d.ts.map +1 -1
- package/src/engine/graphics3/decal/decal_gpu_records.js +26 -5
- package/src/engine/graphics3/decal/decal_material_samplers.d.ts +6 -0
- package/src/engine/graphics3/decal/decal_material_samplers.d.ts.map +1 -1
- package/src/engine/graphics3/decal/decal_material_samplers.js +13 -0
- package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +1 -1
- package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +1 -1
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts +5 -0
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
- package/src/engine/graphics3/decal/shader_decal_composite.js +69 -28
- package/src/engine/network/sim/SimActionExecutor.d.ts +4 -0
- package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
- package/src/engine/network/sim/SimActionExecutor.js +4 -0
- package/src/generation/foliage/material/foliage_atlas_cutout.d.ts.map +1 -1
- package/src/generation/foliage/material/foliage_atlas_cutout.js +21 -5
- package/src/generation/foliage/mesh/tree_cluster_representatives.d.ts +8 -0
- package/src/generation/foliage/mesh/tree_cluster_representatives.d.ts.map +1 -1
- package/src/generation/foliage/mesh/tree_cluster_representatives.js +178 -78
- package/src/generation/foliage/mesh/tree_mesh_build_bark.d.ts.map +1 -1
- package/src/generation/foliage/mesh/tree_mesh_build_bark.js +178 -97
- package/src/generation/foliage/skeleton/ShootLightField.d.ts +1 -0
- package/src/generation/foliage/skeleton/ShootLightField.d.ts.map +1 -1
- package/src/generation/foliage/skeleton/ShootLightField.js +88 -17
- package/src/generation/foliage/skeleton/ShootWoodHash.d.ts +8 -4
- package/src/generation/foliage/skeleton/ShootWoodHash.d.ts.map +1 -1
- package/src/generation/foliage/skeleton/ShootWoodHash.js +216 -27
- package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
- package/src/shade/playground/probe_clipmap/main.js +4 -0
- package/src/shade/playground/probe_clipmap_box/README.md +55 -0
- package/src/shade/playground/probe_clipmap_box/index.html +185 -0
- package/src/shade/playground/probe_clipmap_box/main.d.ts +8 -0
- package/src/shade/playground/probe_clipmap_box/main.d.ts.map +1 -0
- package/src/shade/playground/probe_clipmap_box/main.js +323 -0
- package/src/shade/playground/probe_clipmap_box/scene.d.ts +93 -0
- package/src/shade/playground/probe_clipmap_box/scene.d.ts.map +1 -0
- package/src/shade/playground/probe_clipmap_box/scene.js +256 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +6 -1
- package/src/shade/renderer/buffer/graph_read_buffer.d.ts +3 -1
- package/src/shade/renderer/buffer/graph_read_buffer.d.ts.map +1 -1
- package/src/shade/renderer/buffer/graph_read_buffer.js +9 -6
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_decode.d.ts +12 -0
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_decode.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_decode.js +49 -24
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_encode.d.ts +12 -0
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_encode.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_encode.js +50 -19
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_sh3_compress.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_sh3_compress.js +6 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +5 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +7 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +6 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +10 -9
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +12 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +14 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +17 -22
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +53 -65
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.d.ts +2 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.js +9 -20
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts +2 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +14 -19
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +8 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.js +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.d.ts +2 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.js +13 -18
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.d.ts +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.js +4 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_diffuse.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_diffuse.js +4 -6
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_indirect_lighting.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_indirect_lighting.js +4 -7
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts +4 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js +14 -13
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts +3 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +7 -15
- package/src/shade/renderer/light/environment/shader_downsample_environment_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/shader_downsample_environment_map.js +5 -1
- package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
- package/src/shade/renderer/particles/GPUParticleSystem.js +1 -7
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts +26 -8
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +170 -142
- package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.d.ts +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.js +5 -8
- package/src/shade/renderer/restir/di/chunk_restir_resolve.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/chunk_restir_resolve.js +91 -94
- package/src/shade/renderer/restir/reservoir/chunk_rtxdi_stream_sample.js +1 -1
- package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_decode.d.ts +14 -0
- package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_decode.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_decode.js +36 -21
- package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_sample_gather.d.ts +22 -0
- package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_sample_gather.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_sample_gather.js +64 -0
- package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts +15 -4
- package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.js +33 -7
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_vertex_normal.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_vertex_normal.js +13 -18
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_vertex_normal.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_vertex_normal.js +28 -30
- package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_u32_to_vec2.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_u32_to_vec2.js +15 -16
- package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_vec2_to_u32.d.ts +0 -1
- package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_vec2_to_u32.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_vec2_to_u32.js +15 -18
- package/src/shade/renderer/shader/chunk/noise/chunk_sobol_sample_vec2.d.ts +40 -0
- package/src/shade/renderer/shader/chunk/noise/chunk_sobol_sample_vec2.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/chunk_sobol_sample_vec2.js +75 -0
- package/src/shade/renderer/shader/chunk/noise/chunk_vdc_radical_inverse.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/noise/chunk_vdc_radical_inverse.js +3 -1
- package/src/shade/renderer/shader/chunk/random/chunk_hash_lk.d.ts +28 -0
- package/src/shade/renderer/shader/chunk/random/chunk_hash_lk.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/random/chunk_hash_lk.js +41 -0
- package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_color_add_scaled.d.ts +12 -0
- package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_color_add_scaled.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_color_add_scaled.js +24 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts +3 -2
- package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.js +4 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts +2 -5
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.js +3 -20
- package/src/shade/renderer/water/chunk_water_gi.d.ts +1 -1
- package/src/shade/renderer/water/chunk_water_gi.d.ts.map +1 -1
- package/src/shade/renderer/water/chunk_water_gi.js +6 -8
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +8 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +79 -35
- package/src/core/math/hash/squirrel3.d.ts +0 -17
- package/src/core/math/hash/squirrel3.d.ts.map +0 -1
- package/src/core/math/hash/squirrel3.js +0 -30
- package/src/shade/renderer/global_illumination/brick4/cpu/brick4_sh3_color_encode.d.ts +0 -2
- package/src/shade/renderer/global_illumination/brick4/cpu/brick4_sh3_color_encode.d.ts.map +0 -1
- package/src/shade/renderer/global_illumination/brick4/cpu/brick4_sh3_color_encode.js +0 -6
- package/src/shade/renderer/shader/chunk/random/chunk_hash_squirrel3.d.ts +0 -12
- package/src/shade/renderer/shader/chunk/random/chunk_hash_squirrel3.d.ts.map +0 -1
- package/src/shade/renderer/shader/chunk/random/chunk_hash_squirrel3.js +0 -30
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import Vector3 from "../../../core/geom/Vector3.js";
|
|
2
|
+
import { DEG_TO_RAD } from "../../../core/math/DEG_TO_RAD.js";
|
|
3
|
+
import { EntityComponentDataset } from "../../../engine/ecs/EntityComponentDataset.js";
|
|
4
|
+
import { OrbitalCameraController } from "../../renderer/camera/orbital/OrbitalCameraController.js";
|
|
5
|
+
import { PerspectiveCamera } from "../../renderer/camera/PerspectiveCamera.js";
|
|
6
|
+
import { create_frame_loop } from "../../renderer/create_frame_loop.js";
|
|
7
|
+
import { ProbeClipmapDebugView } from "../../renderer/global_illumination/probe_clipmap/debug/ProbeClipmapDebugView.js";
|
|
8
|
+
import { Renderer } from "../../renderer/Renderer.js";
|
|
9
|
+
import { Scene } from "../../renderer/scene/Scene.js";
|
|
10
|
+
import { ShadeIndirectLightingMode } from "../../renderer/ShadeIndirectLightingMode.js";
|
|
11
|
+
import { BOX_INSIDE, BoxSunAim, build_hole_box } from "./scene.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A closed box with a hole in its ceiling under the probe clipmap GI (`ShadeIndirectLightingMode.ProbeClipmap`):
|
|
15
|
+
* the sun through the hole onto the red wall, the green wall or the floor, and the hole opened or closed, to
|
|
16
|
+
* watch how the probes follow a change in the light and in the world.
|
|
17
|
+
*
|
|
18
|
+
* Runs under the dev server (`npm run dev`); needs no asset. The panel is hand-rolled, as the other
|
|
19
|
+
* playgrounds' are.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Mesh SDF bricks baked a frame while the caches fill, as this page starts: the box's ten slabs are whole in a
|
|
24
|
+
* few frames.
|
|
25
|
+
* @type {number}
|
|
26
|
+
*/
|
|
27
|
+
const PAGE_BAKE_BUDGET = 256;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The exposure the page starts at, f-stops; fixed, since eye adaptation would move the picture for seconds
|
|
31
|
+
* after every change, the very thing the page is for watching.
|
|
32
|
+
* @type {number}
|
|
33
|
+
*/
|
|
34
|
+
const PAGE_EXPOSURE = 3.5;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A frame-time readout, kept as a rolling mean so the number is readable rather than jittering.
|
|
38
|
+
*/
|
|
39
|
+
class FrameTimer {
|
|
40
|
+
#samples = new Float64Array(60);
|
|
41
|
+
#count = 0;
|
|
42
|
+
#cursor = 0;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {number} seconds
|
|
46
|
+
*/
|
|
47
|
+
add(seconds) {
|
|
48
|
+
this.#samples[this.#cursor] = seconds * 1000;
|
|
49
|
+
this.#cursor = (this.#cursor + 1) % this.#samples.length;
|
|
50
|
+
this.#count = Math.min(this.#count + 1, this.#samples.length);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @returns {number} mean frame time in milliseconds, or 0 before there is anything to average
|
|
55
|
+
*/
|
|
56
|
+
get mean_ms() {
|
|
57
|
+
if (this.#count === 0) {
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let total = 0;
|
|
62
|
+
|
|
63
|
+
for (let i = 0; i < this.#count; i++) {
|
|
64
|
+
total += this.#samples[i];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return total / this.#count;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Stand the page up. Called by the page rather than run on import, so that nothing here touches the DOM
|
|
73
|
+
* until there is one.
|
|
74
|
+
*
|
|
75
|
+
* @returns {Promise<void>}
|
|
76
|
+
*/
|
|
77
|
+
export async function start() {
|
|
78
|
+
const element = id => document.getElementById(id);
|
|
79
|
+
|
|
80
|
+
const status_element = element('status');
|
|
81
|
+
const stats_element = element('stats');
|
|
82
|
+
|
|
83
|
+
function set_status(text, kind = '') {
|
|
84
|
+
status_element.textContent = text;
|
|
85
|
+
status_element.className = kind;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const context = element('view').getContext('webgpu');
|
|
89
|
+
|
|
90
|
+
if (context === null) {
|
|
91
|
+
set_status('no WebGPU context — this browser has none, or the page is not a secure context', 'fail');
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const renderer = new Renderer();
|
|
96
|
+
|
|
97
|
+
set_status('acquiring a device…');
|
|
98
|
+
|
|
99
|
+
await renderer.initialize({ context });
|
|
100
|
+
|
|
101
|
+
renderer.indirect_lighting_mode = ShadeIndirectLightingMode.ProbeClipmap;
|
|
102
|
+
renderer.probe_clipmap.mesh_sdf_bake_budget = PAGE_BAKE_BUDGET;
|
|
103
|
+
renderer.feature_automatic_exposure_enabled = false;
|
|
104
|
+
renderer.exposure_compensation = PAGE_EXPOSURE;
|
|
105
|
+
|
|
106
|
+
const camera = new PerspectiveCamera();
|
|
107
|
+
|
|
108
|
+
camera.near = 0.05;
|
|
109
|
+
camera.far = 100;
|
|
110
|
+
camera.fov = 75 * DEG_TO_RAD;
|
|
111
|
+
camera.aspect = renderer.aspect_ratio;
|
|
112
|
+
|
|
113
|
+
const scene = new Scene();
|
|
114
|
+
|
|
115
|
+
// the slabs and the sun stand at entities, so the scene names a dataset for them
|
|
116
|
+
scene.dataset = new EntityComponentDataset();
|
|
117
|
+
|
|
118
|
+
const scene_context = renderer.scenes.obtain(scene);
|
|
119
|
+
|
|
120
|
+
// body rather than the canvas: the controller's keyboard device needs a focusable element
|
|
121
|
+
const controller = new OrbitalCameraController(camera, document.body);
|
|
122
|
+
|
|
123
|
+
const box = await build_hole_box(scene, scene_context, {
|
|
124
|
+
aim: BoxSunAim[element('sun_aim').value],
|
|
125
|
+
open: element('hole_open').checked,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// inside, against the front wall, looking at the back one: both coloured walls and the floor in view
|
|
129
|
+
const h = BOX_INSIDE * 0.5;
|
|
130
|
+
|
|
131
|
+
controller.look(new Vector3(0, 0.44 * BOX_INSIDE, 0.92 * h), new Vector3(0, 0.4 * BOX_INSIDE, -h));
|
|
132
|
+
controller.movement_speed_scale = BOX_INSIDE * 0.05;
|
|
133
|
+
|
|
134
|
+
// handy from the console
|
|
135
|
+
globalThis.renderer = renderer;
|
|
136
|
+
globalThis.scene = scene;
|
|
137
|
+
globalThis.camera = camera;
|
|
138
|
+
globalThis.box = box;
|
|
139
|
+
|
|
140
|
+
// ---- what changed, and when -----------------------------------------------------------
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Frames rendered since the sun or the hole last changed, for the stats line: what the probes have had to
|
|
144
|
+
* follow it.
|
|
145
|
+
* @type {number}
|
|
146
|
+
*/
|
|
147
|
+
let frames_since_change = 0;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* The traced reference no longer matches the box. The tracer restarts on its own when the camera
|
|
151
|
+
* moves, but not when a light or a slab does; while it is off, the restart waits for it to come back
|
|
152
|
+
* on, so that flipping it on a still camera keeps what it has accumulated.
|
|
153
|
+
*/
|
|
154
|
+
let trace_stale = false;
|
|
155
|
+
|
|
156
|
+
function box_changed() {
|
|
157
|
+
frames_since_change = 0;
|
|
158
|
+
|
|
159
|
+
if (renderer.feature_path_tracing_enabled) {
|
|
160
|
+
renderer.path_tracer.clear_history = true;
|
|
161
|
+
} else {
|
|
162
|
+
trace_stale = true;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const sun_aim_select = element('sun_aim');
|
|
167
|
+
const hole_toggle = element('hole_open');
|
|
168
|
+
|
|
169
|
+
function set_aim(name) {
|
|
170
|
+
sun_aim_select.value = name;
|
|
171
|
+
box.aim = BoxSunAim[name];
|
|
172
|
+
box_changed();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function set_open(open) {
|
|
176
|
+
hole_toggle.checked = open;
|
|
177
|
+
box.open = open;
|
|
178
|
+
box_changed();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
sun_aim_select.addEventListener('change', event => set_aim(event.target.value));
|
|
182
|
+
hole_toggle.addEventListener('change', event => set_open(event.target.checked));
|
|
183
|
+
|
|
184
|
+
// ---- controls -------------------------------------------------------------------------
|
|
185
|
+
|
|
186
|
+
element('indirect').addEventListener('change', event => {
|
|
187
|
+
renderer.indirect_lighting_mode = ShadeIndirectLightingMode[event.target.value];
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
element('debug_view').addEventListener('change', event => {
|
|
191
|
+
renderer.probe_clipmap.debug_view = ProbeClipmapDebugView[event.target.value];
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Set by the restart: the next frame renders under IBL, which gives the GI's clipmaps back, and the one
|
|
196
|
+
* after returns to the probes, which build them again from nothing. The geometry caches stay.
|
|
197
|
+
* @type {boolean}
|
|
198
|
+
*/
|
|
199
|
+
let restart_pending = false;
|
|
200
|
+
|
|
201
|
+
function restart_gi() {
|
|
202
|
+
if (renderer.indirect_lighting_mode !== ShadeIndirectLightingMode.ProbeClipmap) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
renderer.indirect_lighting_mode = ShadeIndirectLightingMode.IBL;
|
|
207
|
+
restart_pending = true;
|
|
208
|
+
frames_since_change = 0;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
element('restart').addEventListener('click', restart_gi);
|
|
212
|
+
|
|
213
|
+
const exposure_slider = element('exposure');
|
|
214
|
+
|
|
215
|
+
function show_exposure() {
|
|
216
|
+
element('exposure_value').textContent = `${Number(exposure_slider.value).toFixed(1)}`;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
exposure_slider.value = String(PAGE_EXPOSURE);
|
|
220
|
+
show_exposure();
|
|
221
|
+
exposure_slider.addEventListener('input', () => {
|
|
222
|
+
renderer.exposure_compensation = Number(exposure_slider.value);
|
|
223
|
+
show_exposure();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
const taa_toggle = element('taa');
|
|
227
|
+
const path_tracing_toggle = element('path_tracing');
|
|
228
|
+
|
|
229
|
+
taa_toggle.addEventListener('change', event => {
|
|
230
|
+
renderer.feature_taa_enabled = event.target.checked;
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* What TAA was before the tracer turned it off, to give it back when the tracer goes.
|
|
235
|
+
* @type {boolean}
|
|
236
|
+
*/
|
|
237
|
+
let taa_before_tracing = taa_toggle.checked;
|
|
238
|
+
|
|
239
|
+
function set_path_tracing(enabled) {
|
|
240
|
+
if (enabled === renderer.feature_path_tracing_enabled) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
path_tracing_toggle.checked = enabled;
|
|
245
|
+
renderer.feature_path_tracing_enabled = enabled;
|
|
246
|
+
|
|
247
|
+
// two temporal filters over one image fight; the tracer accumulates on its own
|
|
248
|
+
if (enabled) {
|
|
249
|
+
taa_before_tracing = taa_toggle.checked;
|
|
250
|
+
taa_toggle.checked = false;
|
|
251
|
+
|
|
252
|
+
if (trace_stale) {
|
|
253
|
+
renderer.path_tracer.clear_history = true;
|
|
254
|
+
trace_stale = false;
|
|
255
|
+
}
|
|
256
|
+
} else {
|
|
257
|
+
taa_toggle.checked = taa_before_tracing;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
taa_toggle.disabled = enabled;
|
|
261
|
+
renderer.feature_taa_enabled = taa_toggle.checked;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
path_tracing_toggle.addEventListener('change', event => set_path_tracing(event.target.checked));
|
|
265
|
+
|
|
266
|
+
const AIM_KEYS = { Digit1: 'RedWall', Digit2: 'GreenWall', Digit3: 'Down' };
|
|
267
|
+
|
|
268
|
+
document.addEventListener('keydown', event => {
|
|
269
|
+
// not in a select, where the keys pick an option
|
|
270
|
+
if (event.repeat || event.target instanceof HTMLSelectElement) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (event.code in AIM_KEYS) {
|
|
275
|
+
set_aim(AIM_KEYS[event.code]);
|
|
276
|
+
} else if (event.code === 'KeyH') {
|
|
277
|
+
set_open(!hole_toggle.checked);
|
|
278
|
+
} else if (event.code === 'KeyP') {
|
|
279
|
+
set_path_tracing(!renderer.feature_path_tracing_enabled);
|
|
280
|
+
} else if (event.code === 'KeyK') {
|
|
281
|
+
restart_gi();
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
document.body.focus();
|
|
286
|
+
|
|
287
|
+
set_status('the box is up', 'pass');
|
|
288
|
+
|
|
289
|
+
// ---- frame loop -----------------------------------------------------------------------
|
|
290
|
+
|
|
291
|
+
const frame_timer = new FrameTimer();
|
|
292
|
+
const sdf = scene_context.geometries.sdf;
|
|
293
|
+
|
|
294
|
+
create_frame_loop((time_delta_s, raf_time_s) => {
|
|
295
|
+
const width = window.innerWidth;
|
|
296
|
+
const height = window.innerHeight;
|
|
297
|
+
|
|
298
|
+
renderer.resize(width, height);
|
|
299
|
+
renderer.pixel_ratio = window.devicePixelRatio;
|
|
300
|
+
camera.aspect = width / height;
|
|
301
|
+
|
|
302
|
+
controller.update();
|
|
303
|
+
|
|
304
|
+
renderer.render(camera, scene, time_delta_s);
|
|
305
|
+
|
|
306
|
+
if (restart_pending) {
|
|
307
|
+
restart_pending = false;
|
|
308
|
+
renderer.indirect_lighting_mode = ShadeIndirectLightingMode.ProbeClipmap;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
frames_since_change++;
|
|
312
|
+
frame_timer.add(raf_time_s);
|
|
313
|
+
|
|
314
|
+
const mean = frame_timer.mean_ms;
|
|
315
|
+
const baking = sdf.baking_count + sdf.queued_count;
|
|
316
|
+
|
|
317
|
+
stats_element.textContent =
|
|
318
|
+
`${mean.toFixed(1)} ms · ${mean > 0 ? (1000 / mean).toFixed(0) : '0'} fps\n`
|
|
319
|
+
+ `mesh SDFs: ${sdf.resident_count} resident${baking > 0 ? `, ${baking} baking` : ''}\n`
|
|
320
|
+
+ `frames since the last change: ${frames_since_change}`
|
|
321
|
+
+ `${renderer.feature_path_tracing_enabled ? `\npath traced: ${renderer.path_tracer.min_sample_count} samples` : ''}`;
|
|
322
|
+
}, 60);
|
|
323
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The direction the sun's light travels for an aim, unit, into `out`.
|
|
3
|
+
*
|
|
4
|
+
* @param {Vector3} out
|
|
5
|
+
* @param {BoxSunAim} aim
|
|
6
|
+
* @returns {Vector3} out
|
|
7
|
+
*/
|
|
8
|
+
export function box_sun_direction(out: Vector3, aim: BoxSunAim): Vector3;
|
|
9
|
+
/**
|
|
10
|
+
* The slabs, each [size, centre, colour], every one at unit scale with a geometry of its own size: a mesh's
|
|
11
|
+
* distance field is cached per geometry and composed per instance, so a scaled unit cube would not be one.
|
|
12
|
+
* The side walls stand from the floor's underside to the ceiling's top and the front and back between them,
|
|
13
|
+
* so no seam runs along an inside edge. The ceiling is four pieces around the hole.
|
|
14
|
+
*
|
|
15
|
+
* @returns {{name: string, size: number[], centre: number[], colour: number[]}[]}
|
|
16
|
+
*/
|
|
17
|
+
export function box_slabs(): {
|
|
18
|
+
name: string;
|
|
19
|
+
size: number[];
|
|
20
|
+
centre: number[];
|
|
21
|
+
colour: number[];
|
|
22
|
+
}[];
|
|
23
|
+
/**
|
|
24
|
+
* The lid that closes the hole: the hole's own size, flush with the ceiling.
|
|
25
|
+
*
|
|
26
|
+
* @returns {{name: string, size: number[], centre: number[], colour: number[]}}
|
|
27
|
+
*/
|
|
28
|
+
export function box_lid(): {
|
|
29
|
+
name: string;
|
|
30
|
+
size: number[];
|
|
31
|
+
centre: number[];
|
|
32
|
+
colour: number[];
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* A closed box with a hole in its ceiling, a red wall at −x and a green one at +x, a sun that shines in through
|
|
36
|
+
* the hole, and a flat sky. Built into a scene that names a dataset, whose context is `scene_context`.
|
|
37
|
+
*
|
|
38
|
+
* The hole is closed by placing a lid into it and opened by taking the lid out, so the distance field the
|
|
39
|
+
* GI's rays march changes as a level's would. Closed, nothing reaches the inside: whatever light is left there is
|
|
40
|
+
* what the GI still holds.
|
|
41
|
+
*
|
|
42
|
+
* @param {import("../../renderer/scene/Scene.js").Scene} scene
|
|
43
|
+
* @param {import("../../renderer/scene/GPUSceneContext.js").GPUSceneContext} scene_context
|
|
44
|
+
* @param {object} [options]
|
|
45
|
+
* @param {number} [options.sun_intensity]
|
|
46
|
+
* @param {number[]} [options.sky] linear radiance of the flat sky
|
|
47
|
+
* @param {BoxSunAim} [options.aim]
|
|
48
|
+
* @param {boolean} [options.open]
|
|
49
|
+
*/
|
|
50
|
+
export function build_hole_box(scene: import("../../renderer/scene/Scene.js").Scene, scene_context: import("../../renderer/scene/GPUSceneContext.js").GPUSceneContext, { sun_intensity, sky, aim, open, }?: {
|
|
51
|
+
sun_intensity?: number;
|
|
52
|
+
sky?: number[];
|
|
53
|
+
aim?: BoxSunAim;
|
|
54
|
+
open?: boolean;
|
|
55
|
+
}): Promise<{
|
|
56
|
+
sun: import("../../renderer/light/model/DirectionalLight.js").DirectionalLight;
|
|
57
|
+
aim: number;
|
|
58
|
+
open: boolean;
|
|
59
|
+
}>;
|
|
60
|
+
/**
|
|
61
|
+
* The inside of the box, a side, metres: x and z in [−½, ½] of it, y in [0, 1] of it. Five probe spacings of
|
|
62
|
+
* the finest cascade at the GI's default spacing.
|
|
63
|
+
* @type {number}
|
|
64
|
+
*/
|
|
65
|
+
export const BOX_INSIDE: number;
|
|
66
|
+
/**
|
|
67
|
+
* Every slab's thickness, metres: two voxels of the finest brick at the GI's default voxel, so a wall has an
|
|
68
|
+
* inside the distance field can tell from its outside.
|
|
69
|
+
* @type {number}
|
|
70
|
+
*/
|
|
71
|
+
export const BOX_WALL: number;
|
|
72
|
+
/**
|
|
73
|
+
* The hole in the middle of the ceiling, a side, metres.
|
|
74
|
+
* @type {number}
|
|
75
|
+
*/
|
|
76
|
+
export const BOX_HOLE: number;
|
|
77
|
+
/**
|
|
78
|
+
* How far below the horizon the sun stands when it is aimed at a wall, degrees: through the hole's middle it
|
|
79
|
+
* lands on the wall's middle.
|
|
80
|
+
* @type {number}
|
|
81
|
+
*/
|
|
82
|
+
export const BOX_SUN_WALL_ELEVATION: number;
|
|
83
|
+
/**
|
|
84
|
+
* Where the sun's light falls inside the box, through the hole.
|
|
85
|
+
*/
|
|
86
|
+
export type BoxSunAim = number;
|
|
87
|
+
export namespace BoxSunAim {
|
|
88
|
+
let RedWall: number;
|
|
89
|
+
let GreenWall: number;
|
|
90
|
+
let Down: number;
|
|
91
|
+
}
|
|
92
|
+
import Vector3 from "../../../core/geom/Vector3.js";
|
|
93
|
+
//# sourceMappingURL=scene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/probe_clipmap_box/scene.js"],"names":[],"mappings":"AA4DA;;;;;;GAMG;AACH,uCAJW,OAAO,OACP,SAAS,GACP,OAAO,CAgBnB;AAED;;;;;;;GAOG;AACH,6BAFa;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAC,EAAE,CAwBhF;AAED;;;;GAIG;AACH,2BAFa;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAC,CAI9E;AAgBD;;;;;;;;;;;;;;;GAeG;AACH,sCARW,OAAO,+BAA+B,EAAE,KAAK,iBAC7C,OAAO,yCAAyC,EAAE,eAAe;IAEhD,aAAa,GAA9B,MAAM;IACa,GAAG,GAAtB,MAAM,EAAE;IACY,GAAG,GAAvB,SAAS;IACS,IAAI,GAAtB,OAAO;;;;;GAuGjB;AAnPD;;;;GAIG;AACH,yBAFU,MAAM,CAEY;AAE5B;;;;GAIG;AACH,uBAFU,MAAM,CAEa;AAE7B;;;GAGG;AACH,uBAFU,MAAM,CAEa;AAE7B;;;;GAIG;AACH,qCAFU,MAAM,CAEyB;;;;wBAY/B,MAAM;;;;;;oBA/CI,+BAA+B"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { Color } from "../../../core/color/Color.js";
|
|
2
|
+
import Quaternion from "../../../core/geom/Quaternion.js";
|
|
3
|
+
import Vector3 from "../../../core/geom/Vector3.js";
|
|
4
|
+
import { Transform64 } from "../../../engine/ecs/transform/Transform64.js";
|
|
5
|
+
import { BoxGeometry } from "../../renderer/geometry/BoxGeometry.js";
|
|
6
|
+
import { MeshoptClusterizer } from "../../renderer/geometry/meshlet/build/meshoptimizer/meshopt_clusterizer.js";
|
|
7
|
+
import { make_sunlight } from "../../renderer/light/make_sunlight.js";
|
|
8
|
+
import { place_light } from "../../renderer/light/place_light.js";
|
|
9
|
+
import { StandardShadeMaterial } from "../../renderer/material/StandardShadeMaterial.js";
|
|
10
|
+
import { place_primitive, remove_primitive } from "../../renderer/scene/rows/place_primitive.js";
|
|
11
|
+
import { make_flat_environment } from "../skinned_blas_refit/flat_environment.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The inside of the box, a side, metres: x and z in [−½, ½] of it, y in [0, 1] of it. Five probe spacings of
|
|
15
|
+
* the finest cascade at the GI's default spacing.
|
|
16
|
+
* @type {number}
|
|
17
|
+
*/
|
|
18
|
+
export const BOX_INSIDE = 5;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Every slab's thickness, metres: two voxels of the finest brick at the GI's default voxel, so a wall has an
|
|
22
|
+
* inside the distance field can tell from its outside.
|
|
23
|
+
* @type {number}
|
|
24
|
+
*/
|
|
25
|
+
export const BOX_WALL = 0.25;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The hole in the middle of the ceiling, a side, metres.
|
|
29
|
+
* @type {number}
|
|
30
|
+
*/
|
|
31
|
+
export const BOX_HOLE = 1.25;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* How far below the horizon the sun stands when it is aimed at a wall, degrees: through the hole's middle it
|
|
35
|
+
* lands on the wall's middle.
|
|
36
|
+
* @type {number}
|
|
37
|
+
*/
|
|
38
|
+
export const BOX_SUN_WALL_ELEVATION = 45;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The classic Cornell box reflectances.
|
|
42
|
+
*/
|
|
43
|
+
const WHITE = [0.73, 0.73, 0.73];
|
|
44
|
+
const RED = [0.63, 0.065, 0.05];
|
|
45
|
+
const GREEN = [0.14, 0.45, 0.091];
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Where the sun's light falls inside the box, through the hole.
|
|
49
|
+
* @readonly
|
|
50
|
+
* @enum {number}
|
|
51
|
+
*/
|
|
52
|
+
export const BoxSunAim = {
|
|
53
|
+
/** onto the red wall, at −x, from high over +x */
|
|
54
|
+
RedWall: 0,
|
|
55
|
+
/** onto the green wall, at +x, from high over −x */
|
|
56
|
+
GreenWall: 1,
|
|
57
|
+
/** straight down onto the middle of the floor */
|
|
58
|
+
Down: 2,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The direction the sun's light travels for an aim, unit, into `out`.
|
|
63
|
+
*
|
|
64
|
+
* @param {Vector3} out
|
|
65
|
+
* @param {BoxSunAim} aim
|
|
66
|
+
* @returns {Vector3} out
|
|
67
|
+
*/
|
|
68
|
+
export function box_sun_direction(out, aim) {
|
|
69
|
+
const elevation = BOX_SUN_WALL_ELEVATION * Math.PI / 180;
|
|
70
|
+
|
|
71
|
+
if (aim === BoxSunAim.RedWall) {
|
|
72
|
+
out.set(-Math.cos(elevation), -Math.sin(elevation), 0);
|
|
73
|
+
} else if (aim === BoxSunAim.GreenWall) {
|
|
74
|
+
out.set(Math.cos(elevation), -Math.sin(elevation), 0);
|
|
75
|
+
} else if (aim === BoxSunAim.Down) {
|
|
76
|
+
out.set(0, -1, 0);
|
|
77
|
+
} else {
|
|
78
|
+
throw new Error(`unknown sun aim ${aim}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The slabs, each [size, centre, colour], every one at unit scale with a geometry of its own size: a mesh's
|
|
86
|
+
* distance field is cached per geometry and composed per instance, so a scaled unit cube would not be one.
|
|
87
|
+
* The side walls stand from the floor's underside to the ceiling's top and the front and back between them,
|
|
88
|
+
* so no seam runs along an inside edge. The ceiling is four pieces around the hole.
|
|
89
|
+
*
|
|
90
|
+
* @returns {{name: string, size: number[], centre: number[], colour: number[]}[]}
|
|
91
|
+
*/
|
|
92
|
+
export function box_slabs() {
|
|
93
|
+
const h = BOX_INSIDE * 0.5;
|
|
94
|
+
const t = BOX_WALL;
|
|
95
|
+
const a = BOX_HOLE * 0.5;
|
|
96
|
+
const outer = BOX_INSIDE + 2 * t;
|
|
97
|
+
const tall = BOX_INSIDE + 2 * t;
|
|
98
|
+
const mid = BOX_INSIDE * 0.5;
|
|
99
|
+
const top = BOX_INSIDE + t * 0.5;
|
|
100
|
+
// a ceiling piece beside the hole, along x, from the hole's edge to the outside
|
|
101
|
+
const strip = h + t - a;
|
|
102
|
+
|
|
103
|
+
return [
|
|
104
|
+
{ name: 'floor', size: [outer, t, outer], centre: [0, -t * 0.5, 0], colour: WHITE },
|
|
105
|
+
{ name: 'red wall', size: [t, tall, outer], centre: [-h - t * 0.5, mid, 0], colour: RED },
|
|
106
|
+
{ name: 'green wall', size: [t, tall, outer], centre: [h + t * 0.5, mid, 0], colour: GREEN },
|
|
107
|
+
{ name: 'back wall', size: [BOX_INSIDE, tall, t], centre: [0, mid, -h - t * 0.5], colour: WHITE },
|
|
108
|
+
{ name: 'front wall', size: [BOX_INSIDE, tall, t], centre: [0, mid, h + t * 0.5], colour: WHITE },
|
|
109
|
+
{ name: 'ceiling, back', size: [outer, t, strip], centre: [0, top, -a - strip * 0.5], colour: WHITE },
|
|
110
|
+
{ name: 'ceiling, front', size: [outer, t, strip], centre: [0, top, a + strip * 0.5], colour: WHITE },
|
|
111
|
+
{ name: 'ceiling, left', size: [strip, t, BOX_HOLE], centre: [-a - strip * 0.5, top, 0], colour: WHITE },
|
|
112
|
+
{ name: 'ceiling, right', size: [strip, t, BOX_HOLE], centre: [a + strip * 0.5, top, 0], colour: WHITE },
|
|
113
|
+
];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The lid that closes the hole: the hole's own size, flush with the ceiling.
|
|
118
|
+
*
|
|
119
|
+
* @returns {{name: string, size: number[], centre: number[], colour: number[]}}
|
|
120
|
+
*/
|
|
121
|
+
export function box_lid() {
|
|
122
|
+
return { name: 'lid', size: [BOX_HOLE, BOX_WALL, BOX_HOLE], centre: [0, BOX_INSIDE + BOX_WALL * 0.5, 0], colour: WHITE };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* @param {number[]} rgb linear
|
|
127
|
+
* @returns {StandardShadeMaterial}
|
|
128
|
+
*/
|
|
129
|
+
function diffuse(rgb) {
|
|
130
|
+
const material = new StandardShadeMaterial();
|
|
131
|
+
|
|
132
|
+
material.diffuse_color.copy(new Color(rgb[0], rgb[1], rgb[2]));
|
|
133
|
+
material.roughness_factor = 1;
|
|
134
|
+
material.metallic_factor = 0;
|
|
135
|
+
|
|
136
|
+
return material;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* A closed box with a hole in its ceiling, a red wall at −x and a green one at +x, a sun that shines in through
|
|
141
|
+
* the hole, and a flat sky. Built into a scene that names a dataset, whose context is `scene_context`.
|
|
142
|
+
*
|
|
143
|
+
* The hole is closed by placing a lid into it and opened by taking the lid out, so the distance field the
|
|
144
|
+
* GI's rays march changes as a level's would. Closed, nothing reaches the inside: whatever light is left there is
|
|
145
|
+
* what the GI still holds.
|
|
146
|
+
*
|
|
147
|
+
* @param {import("../../renderer/scene/Scene.js").Scene} scene
|
|
148
|
+
* @param {import("../../renderer/scene/GPUSceneContext.js").GPUSceneContext} scene_context
|
|
149
|
+
* @param {object} [options]
|
|
150
|
+
* @param {number} [options.sun_intensity]
|
|
151
|
+
* @param {number[]} [options.sky] linear radiance of the flat sky
|
|
152
|
+
* @param {BoxSunAim} [options.aim]
|
|
153
|
+
* @param {boolean} [options.open]
|
|
154
|
+
*/
|
|
155
|
+
export async function build_hole_box(scene, scene_context, {
|
|
156
|
+
sun_intensity = 7.2,
|
|
157
|
+
sky = [0.2, 0.25, 0.35],
|
|
158
|
+
aim = BoxSunAim.RedWall,
|
|
159
|
+
open = true,
|
|
160
|
+
} = {}) {
|
|
161
|
+
// meshlet geometry is built as it is made
|
|
162
|
+
await MeshoptClusterizer.ready;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* @param {{name: string, size: number[], centre: number[], colour: number[]}} slab
|
|
166
|
+
* @param {BoxGeometry} geometry
|
|
167
|
+
* @param {StandardShadeMaterial} material
|
|
168
|
+
* @returns {number} the entity
|
|
169
|
+
*/
|
|
170
|
+
function place(slab, geometry, material) {
|
|
171
|
+
const transform = new Transform64();
|
|
172
|
+
|
|
173
|
+
transform.setTranslation(slab.centre[0], slab.centre[1], slab.centre[2]);
|
|
174
|
+
transform.updateMatrix();
|
|
175
|
+
|
|
176
|
+
return place_primitive(scene_context, geometry, material, transform, { name: slab.name });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
for (const slab of box_slabs()) {
|
|
180
|
+
place(slab, new BoxGeometry(slab.size[0], slab.size[1], slab.size[2]), diffuse(slab.colour));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const lid = box_lid();
|
|
184
|
+
const lid_geometry = new BoxGeometry(lid.size[0], lid.size[1], lid.size[2]);
|
|
185
|
+
const lid_material = diffuse(lid.colour);
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* The lid's entity while it closes the hole, -1 while the hole is open.
|
|
189
|
+
* @type {number}
|
|
190
|
+
*/
|
|
191
|
+
let lid_entity = -1;
|
|
192
|
+
|
|
193
|
+
scene.lights.environment = make_flat_environment(sky);
|
|
194
|
+
|
|
195
|
+
const sun = make_sunlight({ intensity: sun_intensity });
|
|
196
|
+
|
|
197
|
+
place_light(scene, sun);
|
|
198
|
+
|
|
199
|
+
const direction = new Vector3();
|
|
200
|
+
const rotation = new Quaternion();
|
|
201
|
+
|
|
202
|
+
let current_aim = aim;
|
|
203
|
+
|
|
204
|
+
const box = {
|
|
205
|
+
sun,
|
|
206
|
+
|
|
207
|
+
get aim() {
|
|
208
|
+
return current_aim;
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @param {BoxSunAim} v
|
|
213
|
+
*/
|
|
214
|
+
set aim(v) {
|
|
215
|
+
box_sun_direction(direction, v);
|
|
216
|
+
|
|
217
|
+
rotation.fromUnitVectors(Vector3.forward, direction);
|
|
218
|
+
rotation.normalize();
|
|
219
|
+
|
|
220
|
+
sun.transform.setRotation(rotation.x, rotation.y, rotation.z, rotation.w);
|
|
221
|
+
sun.transform.updateMatrix();
|
|
222
|
+
|
|
223
|
+
// a light changed in place reaches the GPU only through the collection's version; without it the
|
|
224
|
+
// shadow cascades, which read the transform themselves, turn and the light does not
|
|
225
|
+
scene.lights.needsUpdate = true;
|
|
226
|
+
|
|
227
|
+
current_aim = v;
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
get open() {
|
|
231
|
+
return lid_entity === -1;
|
|
232
|
+
},
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* @param {boolean} v
|
|
236
|
+
*/
|
|
237
|
+
set open(v) {
|
|
238
|
+
if (v === (lid_entity === -1)) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (v) {
|
|
243
|
+
remove_primitive(scene_context, lid_entity);
|
|
244
|
+
lid_entity = -1;
|
|
245
|
+
} else {
|
|
246
|
+
lid_entity = place(lid, lid_geometry, lid_material);
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
box.aim = aim;
|
|
253
|
+
box.open = open;
|
|
254
|
+
|
|
255
|
+
return box;
|
|
256
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Renderer.d.ts","sourceRoot":"","sources":["../../../../src/shade/renderer/Renderer.js"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"Renderer.d.ts","sourceRoot":"","sources":["../../../../src/shade/renderer/Renderer.js"],"names":[],"mappings":"AA0JA;IAOI,0BAEC;IAED;;OAEG;IACH,0BAAQ;IAER;;;;;;OAMG;IACH,kDAEC;IAED;;OAEG;IACH,kBAAO;IAYP;;;OAGG;IACH,2BAEC;IAaD,wCAGC;IAED,uCAEC;IAED;;;;OAIG;IACH,wBAFU,yBAAyB,CAEoB;IAEvD;;;;;;;OAOG;IACH,mBAFU,gBAAgB,CAEgB;IAE1C;;;;OAIG;IACH,eAFU,oBAAoB,CAEa;IAY3C;;;;;;;OAOG;IACH,mBAFU,qBAAqB,CAEkB;IAEjD;;;;;OAKG;IACH,mBAFU,oBAAoB,CAEgB;IAE9C;;;OAGG;IACH,QAFU,cAAc,CAEM;IAE9B;;;;;;;;;OASG;IACH,2BAFU,OAAO,CAEiB;IAElC,6BAA4B;IAC5B,8BAA4B;IAC5B;;;;OAIG;IACH,mCAAkC;IAClC;;;;;;;OAOG;IACH,mCAFU,OAAO,CAEyB;IAW1C,oCAIC;IAED,mCAEC;IAYD,oCAIC;IAED,mCAEC;IAED;;;;;;OAMG;IACH,6BAFU,OAAO,CAEmB;IAcpC;;OAEG;IACH,uCAEC;IAyBD,0CAIC;IAED,yCAEC;IAED;;;;;OAKG;IACH,yBAFU,MAAM,CAEY;IAW5B,8CAMC;IAED,6CAEC;IAUD,8CAMC;IAED,6CAEC;IAWD,mDAKC;IAED,kDAEC;IASD,+CAKC;IAED,8CAEC;IAED,+BAA6B;IAC7B,4CAA0C;IAkB1C,qCAKC;IArBD;;;;;;;;;;OAUG;IACH,oCAGC;IASD;;;;;;;OAOG;IACH,0BAFU,OAAO,CAEe;IAQhC;;;;;;;OAOG;IACH,oCAOC;IAnBD,mCAEC;IAmBD;;;;;;;;;OASG;IACH,6BAFU,OAAO,CAEmB;IAWpC;;;;;OAKG;IACH,8BAA+C;IAE/C;;;;;;;;OAQG;IACH,6BAFU,OAAO,CAEmB;IAEpC;;;;;;;;;;;;;;OAcG;IACH,8BAFU,OAAO,CAEoB;IAErC;;;;;;;;;;OAUG;IACH,qBAFU,OAAO,CAEW;IAU5B;;;;;OAKG;IACH,wBAA0C;IAE1C;;;;;;;;OAQG;IACH,eAFU,UAAU,GAAC,QAAQ,CAEF;IAU3B;;;;OAIG;IACH,gCAAwD;IAExD;;;OAGG;IACH,4BAFU,OAAO,CAEiB;IAKlC;;;OAGG;IACH,yBAEC;IAYD;;OAEG;IACH,sCAEC;IAOD;;;OAGG;IACH,gCAEC;IAcD;;;;;;;;;OASG;IACH,qBAA+B;IAE/B;;;;;;;;;;OAUG;IACH,qBAA+B;IAgB/B;;;OAGG;IACH,yCAeC;IAED;;;OAGG;IACH,wCAEC;IA0BD;;;OAGG;IACH,iCAEC;IAED;;;;OAIG;IACH,2BAEC;IAQD;;;OAGG;IACH,+CAIC;IAED;;;OAGG;IACH,gDAIC;IAeD;;;OAGG;IACH,gDAIC;IAED;;;;OAIG;IACH,iDAIC;IAkCD;;;OAGG;IACH,+BAcC;IA1BD;;;OAGG;IACH,0BAEC;IAsBD;;;;;;;;;;;;;;;;;;;OAmBG;IACH,iBAFU,iBAAiB,GAAC,IAAI,CAET;IAEvB;;OAEG;IACH;;;;;;;;;;;;;;OAcG;IACH,yBAHW,eAAe,GACb,eAAe,CA8B3B;IAED;;;;;OAKG;IACH,4BAHW,eAAe,GACb,OAAO,CAInB;IAED;;;OAGG;IACH,uBAHW,UAAU,GACR,MAAM,CAIlB;IAUD;;;;;;;;;;;;;;;;;OAiBG;IACH,kCAHW,iBAAiB,GACf,iBAAiB,CAsB7B;IAED;;;;;OAKG;IACH,qCAHW,iBAAiB,GACf,OAAO,CAYnB;IAED;;OAEG;IACH,8BAFa,MAAM,CAIlB;IAgBD;;;;OAIG;IACH,yBAHW,KAAK,GACJ,gBAAgB,CAW3B;IAED;;;OAGG;IACH,6BAMC;IAiBD;;;;OAIG;IACH,gCAHW,KAAK,GACH,2BAA2B,CAcvC;IAGD;;;OAGG;IACH,kBAFW,KAAK,QAyBf;IAiSD,oGAAoG;IACpG,kDAA2C;IAO3C;;;;OAIG;IACH,0BAEC;IAiBD;;;;;;OAMG;IACH,qBAHW,eAAe,GACb,iBAAiB,CAW7B;IAgBD;;;;;;OAMG;IACH,cAFU,iBAAiB,CAEU;IAErC;;;;;;OAMG;IACH,eAgBC;IAwFD;;;;;;;;OAQG;IACH;QAJsC,OAAO;QACd,MAAM;QACT,UAAU,GAA3B,MAAM;sBAuNhB;IAED;;;;;;;;;;;;;;OAcG;IACH,0BAFW,eAAe,QAkEzB;IAyDD;;;;;;;;;;;;;;;;;OAiBG;IACH,WAFa,IAAI,CA0ChB;IAkCD,4BAwBC;IAkID;;;;;OAKG;IACH,UAHW,MAAM,KACN,MAAM,QAgBhB;IAoFD,0CAMC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,eAZW,iBAAiB,SACjB,KAAK,uBACL,MAAM,GAIJ,OAAO,CAuCnB;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,yBARW,iBAAiB,SACjB,KAAK,sBACL,MAAM,UACN,iBAAiB,GACf,OAAO,CAiBnB;;CAsmCJ;+BA75GY,OAAO,8CAA8C,EAAE,gBAAgB;gCACvE,OAAO,+CAA+C,EAAE,iBAAiB;gCACzE,OAAO,+BAA+B,EAAE,iBAAiB;8BACzD,OAAO,gCAAgC,EAAE,eAAe;gCACxD,OAAO,gDAAgD,EAAE,iBAAiB;8BAC1E,OAAO,4BAA4B,EAAE,eAAe;oBACpD,OAAO,kBAAkB,EAAE,KAAK;6BApChB,yBAAyB;0CACZ,gCAAgC;iCACzC,yCAAyC;qCA9CrC,6DAA6D;sCAgD5D,4BAA4B;qCAD7B,2BAA2B;+BAEjC,6CAA6C;gCAC5C,sCAAsC;2BAjC3C,yCAAyC;6BAFvC,4CAA4C;8BAD3C,2CAA2C;4BAwD7C,uBAAuB;mCAChB,qCAAqC;gCApExC,sBAAsB;oBAzDlC,4BAA4B;kCAyHd,gCAAgC;2BAzFvC,2BAA2B;iCAuFrB,0CAA0C;4CApE/B,+DAA+D;yBA6ClF,yBAAyB;kCAChB,kCAAkC;kCAWlC,wBAAwB;oBApCtC,0BAA0B;gCA3Dd,uCAAuC;uCAiDhC,sDAAsD"}
|