@woosh/meep-engine 3.14.0 → 3.14.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/README.md +33 -64
- package/package.json +1 -1
- package/src/avif/native/DECISIONS.md +544 -536
- package/src/avif/native/heif/parse_avif_file.d.ts.map +1 -1
- package/src/avif/native/heif/parse_avif_file.js +384 -383
- package/src/avif/native/heif/parse_image_grid.d.ts.map +1 -1
- package/src/avif/native/heif/parse_image_grid.js +49 -48
- package/src/basis/BasisBitReader.d.ts +77 -0
- package/src/basis/BasisBitReader.d.ts.map +1 -0
- package/src/basis/BasisBitReader.js +231 -0
- package/src/basis/BasisHuffmanTable.d.ts +53 -0
- package/src/basis/BasisHuffmanTable.d.ts.map +1 -0
- package/src/basis/BasisHuffmanTable.js +263 -0
- package/src/basis/basis_read_huffman_table.d.ts +20 -0
- package/src/basis/basis_read_huffman_table.d.ts.map +1 -0
- package/src/basis/basis_read_huffman_table.js +187 -0
- package/src/basis/etc1s/Etc1sSelectorHistory.d.ts +50 -0
- package/src/basis/etc1s/Etc1sSelectorHistory.d.ts.map +1 -0
- package/src/basis/etc1s/Etc1sSelectorHistory.js +89 -0
- package/src/basis/etc1s/etc1s_block_colors.d.ts +14 -0
- package/src/basis/etc1s/etc1s_block_colors.d.ts.map +1 -0
- package/src/basis/etc1s/etc1s_block_colors.js +75 -0
- package/src/basis/etc1s/etc1s_decode_slice.d.ts +57 -0
- package/src/basis/etc1s/etc1s_decode_slice.d.ts.map +1 -0
- package/src/basis/etc1s/etc1s_decode_slice.js +258 -0
- package/src/basis/etc1s/etc1s_read_endpoint_codebook.d.ts +48 -0
- package/src/basis/etc1s/etc1s_read_endpoint_codebook.d.ts.map +1 -0
- package/src/basis/etc1s/etc1s_read_endpoint_codebook.js +111 -0
- package/src/basis/etc1s/etc1s_read_selector_codebook.d.ts +42 -0
- package/src/basis/etc1s/etc1s_read_selector_codebook.d.ts.map +1 -0
- package/src/basis/etc1s/etc1s_read_selector_codebook.js +127 -0
- package/src/basis/etc1s/etc1s_read_slice_tables.d.ts +54 -0
- package/src/basis/etc1s/etc1s_read_slice_tables.d.ts.map +1 -0
- package/src/basis/etc1s/etc1s_read_slice_tables.js +47 -0
- package/src/basis/transcode/build_range_plan.js +54 -0
- package/src/basis/transcode/etc1s_to_bc1.d.ts +24 -0
- package/src/basis/transcode/etc1s_to_bc1.d.ts.map +1 -0
- package/src/basis/transcode/etc1s_to_bc1.js +205 -0
- package/src/basis/transcode/etc1s_to_bc7.d.ts +30 -0
- package/src/basis/transcode/etc1s_to_bc7.d.ts.map +1 -0
- package/src/basis/transcode/etc1s_to_bc7.js +496 -0
- package/src/basis/transcode/fit_endpoints.d.ts +59 -0
- package/src/basis/transcode/fit_endpoints.d.ts.map +1 -0
- package/src/basis/transcode/fit_endpoints.js +226 -0
- package/src/{avif/native/isobmff → core/binary}/ByteCursor.d.ts +19 -6
- package/src/core/binary/ByteCursor.d.ts.map +1 -0
- package/src/{avif/native/isobmff → core/binary}/ByteCursor.js +41 -14
- package/src/engine/EngineHarness.js +1 -1
- package/src/engine/asset/codec/Codec.d.ts.map +1 -0
- package/src/engine/asset/codec/CodecWithFallback.d.ts.map +1 -0
- package/src/engine/asset/{loaders/image/codec → codec}/CodecWithFallback.js +2 -2
- package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +4 -4
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts +1 -1
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts.map +1 -1
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +1 -1
- package/src/engine/asset/loaders/image/codec/NativeImageDecoder.d.ts +1 -1
- package/src/engine/asset/loaders/image/codec/NativeImageDecoder.d.ts.map +1 -1
- package/src/engine/asset/loaders/image/codec/NativeImageDecoder.js +1 -1
- package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.d.ts +1 -1
- package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.d.ts.map +1 -1
- package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.js +1 -1
- package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts.map +1 -1
- package/src/engine/graphics/texture/atlas/TextureAtlas.js +13 -0
- package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
- package/src/engine/physics/broadphase/generate_pairs.js +7 -1
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/ktx2/KTX2_IDENTIFIER.d.ts +14 -0
- package/src/ktx2/KTX2_IDENTIFIER.d.ts.map +1 -0
- package/src/ktx2/KTX2_IDENTIFIER.js +15 -0
- package/src/ktx2/KhrDfModel.d.ts +35 -0
- package/src/ktx2/KhrDfModel.d.ts.map +1 -0
- package/src/ktx2/KhrDfModel.js +49 -0
- package/src/ktx2/SupercompressionScheme.d.ts +16 -0
- package/src/ktx2/SupercompressionScheme.d.ts.map +1 -0
- package/src/ktx2/SupercompressionScheme.js +23 -0
- package/src/ktx2/ktx2_read.d.ts +71 -0
- package/src/ktx2/ktx2_read.d.ts.map +1 -0
- package/src/ktx2/ktx2_read.js +581 -0
- package/src/ktx2/ktx2_read_basis_lz_global_data.d.ts +27 -0
- package/src/ktx2/ktx2_read_basis_lz_global_data.d.ts.map +1 -0
- package/src/ktx2/ktx2_read_basis_lz_global_data.js +189 -0
- package/src/ktx2/vk_format_to_texture_format.d.ts +55 -0
- package/src/ktx2/vk_format_to_texture_format.d.ts.map +1 -0
- package/src/ktx2/vk_format_to_texture_format.js +290 -0
- package/src/shade/descriptor/GPUTextureUsage.d.ts +23 -0
- package/src/shade/descriptor/GPUTextureUsage.d.ts.map +1 -0
- package/src/shade/descriptor/GPUTextureUsage.js +24 -0
- package/src/shade/descriptor/WebGPUExtensionType.d.ts +3 -0
- package/src/shade/descriptor/WebGPUExtensionType.js +26 -0
- package/src/shade/descriptor/texture/TextureDescriptor.d.ts +2 -6
- package/src/shade/descriptor/texture/TextureDescriptor.d.ts.map +1 -1
- package/src/shade/descriptor/texture/TextureDescriptor.js +24 -40
- package/src/shade/descriptor/texture/format/TextureFormat.d.ts +125 -0
- package/src/shade/descriptor/texture/format/TextureFormat.d.ts.map +1 -0
- package/src/shade/descriptor/texture/format/TextureFormat.js +146 -0
- package/src/shade/descriptor/texture/format/gpu_texture_format_info.d.ts +60 -0
- package/src/shade/descriptor/texture/format/gpu_texture_format_info.d.ts.map +1 -1
- package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +102 -0
- package/src/shade/device/graph/TextureResourceDescriptor.d.ts.map +1 -1
- package/src/shade/device/graph/TextureResourceDescriptor.js +160 -155
- package/src/shade/device/mock/SoftwareGPUQueue.d.ts +11 -4
- package/src/shade/device/mock/SoftwareGPUQueue.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUQueue.js +31 -37
- package/src/shade/device/mock/SoftwareGPUTexture.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUTexture.js +8 -4
- package/src/shade/device/timing/profile/frame_graph_extract_topology.d.ts.map +1 -1
- package/src/shade/device/timing/profile/frame_graph_extract_topology.js +164 -174
- package/src/shade/playground/ground_seam/README.md +235 -0
- package/src/shade/playground/ground_seam/capture_scene_color.d.ts +45 -0
- package/src/shade/playground/ground_seam/capture_scene_color.d.ts.map +1 -0
- package/src/shade/playground/ground_seam/capture_scene_color.js +242 -0
- package/src/shade/playground/ground_seam/depth_step_across_seam.d.ts +11 -0
- package/src/shade/playground/ground_seam/depth_step_across_seam.d.ts.map +1 -0
- package/src/shade/playground/ground_seam/depth_step_across_seam.js +185 -0
- package/src/shade/playground/ground_seam/index.html +195 -0
- package/src/shade/playground/ground_seam/main.d.ts +2 -0
- package/src/shade/playground/ground_seam/main.d.ts.map +1 -0
- package/src/shade/playground/ground_seam/main.js +879 -0
- package/src/shade/playground/ground_seam/make_grid_texture.d.ts +29 -0
- package/src/shade/playground/ground_seam/make_grid_texture.d.ts.map +1 -0
- package/src/shade/playground/ground_seam/make_grid_texture.js +105 -0
- package/src/shade/playground/ground_seam/make_ground.d.ts +70 -0
- package/src/shade/playground/ground_seam/make_ground.d.ts.map +1 -0
- package/src/shade/playground/ground_seam/make_ground.js +161 -0
- package/src/shade/playground/ground_seam/measure_flicker.d.ts +71 -0
- package/src/shade/playground/ground_seam/measure_flicker.d.ts.map +1 -0
- package/src/shade/playground/ground_seam/measure_flicker.js +531 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +2519 -2511
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
- package/src/shade/renderer/hiz/HierarchicalZBuffer.js +275 -274
- package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
- package/src/shade/renderer/light/GPULightCollection.js +323 -314
- package/src/shade/renderer/lightmap/GPULightMap.js +336 -336
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +12 -2
- package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
- package/src/shade/renderer/material/standard/fragment_gbuffer.js +3 -1
- package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
- package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js +3 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.js +3 -1
- package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.js +3 -1
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.d.ts +28 -0
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.js +39 -0
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.d.ts +45 -0
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.js +94 -61
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.d.ts +24 -0
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.js +43 -0
- package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +1462 -0
- package/src/shade/renderer/texture/TextureManager.d.ts.map +1 -1
- package/src/shade/renderer/texture/TextureManager.js +20 -8
- package/src/shade/renderer/texture/TextureRole.d.ts +19 -0
- package/src/shade/renderer/texture/TextureRole.d.ts.map +1 -0
- package/src/shade/renderer/texture/TextureRole.js +26 -0
- package/src/shade/renderer/texture/TextureVariantSet.d.ts +71 -0
- package/src/shade/renderer/texture/TextureVariantSet.d.ts.map +1 -0
- package/src/shade/renderer/texture/TextureVariantSet.js +105 -0
- package/src/shade/renderer/texture/download_texture_data.d.ts.map +1 -1
- package/src/shade/renderer/texture/download_texture_data.js +22 -0
- package/src/shade/renderer/texture/format/gpu_texture_compression_support.d.ts +15 -0
- package/src/shade/renderer/texture/format/gpu_texture_compression_support.d.ts.map +1 -0
- package/src/shade/renderer/texture/format/gpu_texture_compression_support.js +50 -0
- package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.d.ts +27 -0
- package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.d.ts.map +1 -0
- package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.js +65 -0
- package/src/shade/renderer/texture/format/infer_format_from_parameters.d.ts +11 -0
- package/src/shade/renderer/texture/format/infer_format_from_parameters.d.ts.map +1 -0
- package/src/shade/renderer/texture/format/infer_format_from_parameters.js +88 -0
- package/src/shade/renderer/texture/format/texture_format_from_shade_image.d.ts +24 -0
- package/src/shade/renderer/texture/format/texture_format_from_shade_image.d.ts.map +1 -0
- package/src/shade/renderer/texture/format/texture_format_from_shade_image.js +71 -0
- package/src/shade/renderer/texture/format/texture_format_preference.d.ts +22 -0
- package/src/shade/renderer/texture/format/texture_format_preference.d.ts.map +1 -0
- package/src/shade/renderer/texture/format/texture_format_preference.js +89 -0
- package/src/shade/renderer/texture/format/texture_variant_select.d.ts +24 -0
- package/src/shade/renderer/texture/format/texture_variant_select.d.ts.map +1 -0
- package/src/shade/renderer/texture/format/texture_variant_select.js +38 -0
- package/src/shade/renderer/texture/shade_texture_might_have_alpha.d.ts +9 -1
- package/src/shade/renderer/texture/shade_texture_might_have_alpha.d.ts.map +1 -1
- package/src/shade/renderer/texture/shade_texture_might_have_alpha.js +73 -8
- package/src/shade/renderer/texture/source/AlphaMode.d.ts +27 -0
- package/src/shade/renderer/texture/source/AlphaMode.d.ts.map +1 -0
- package/src/shade/renderer/texture/source/AlphaMode.js +52 -0
- package/src/shade/renderer/texture/source/ShadeImage.d.ts +33 -0
- package/src/shade/renderer/texture/source/ShadeImage.d.ts.map +1 -1
- package/src/shade/renderer/texture/source/ShadeImage.js +74 -0
- package/src/shade/renderer/texture/source/ShadeTexelData.d.ts +78 -0
- package/src/shade/renderer/texture/source/ShadeTexelData.d.ts.map +1 -0
- package/src/shade/renderer/texture/source/ShadeTexelData.js +158 -0
- package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.d.ts +0 -10
- package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.d.ts.map +1 -1
- package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.js +73 -175
- package/src/shade/renderer/texture/texture_write_level.d.ts +32 -0
- package/src/shade/renderer/texture/texture_write_level.d.ts.map +1 -0
- package/src/shade/renderer/texture/texture_write_level.js +77 -0
- package/src/shade/renderer/texture/texture_write_to_gpu.d.ts +8 -1
- package/src/shade/renderer/texture/texture_write_to_gpu.d.ts.map +1 -1
- package/src/shade/renderer/texture/texture_write_to_gpu.js +62 -37
- package/src/shade/renderer/texture/virtual/source/VTSourceImage.d.ts +8 -0
- package/src/shade/renderer/texture/virtual/source/VTSourceImage.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/source/VTSourceImage.js +8 -0
- package/src/shade/util/texture_mip_extent.d.ts +49 -0
- package/src/shade/util/texture_mip_extent.d.ts.map +1 -0
- package/src/shade/util/texture_mip_extent.js +87 -0
- package/src/avif/native/isobmff/ByteCursor.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/codec/Codec.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/codec/CodecWithFallback.d.ts.map +0 -1
- package/src/shade/util/compute_max_mip_count.d.ts +0 -8
- package/src/shade/util/compute_max_mip_count.d.ts.map +0 -1
- package/src/shade/util/compute_max_mip_count.js +0 -27
- /package/src/engine/asset/{loaders/image/codec → codec}/Codec.d.ts +0 -0
- /package/src/engine/asset/{loaders/image/codec → codec}/Codec.js +0 -0
- /package/src/engine/asset/{loaders/image/codec → codec}/CodecWithFallback.d.ts +0 -0
|
@@ -1,314 +1,323 @@
|
|
|
1
|
-
import { assert } from "../../../core/assert.js";
|
|
2
|
-
import { ShadeGPUCommandContext } from "../../device/ShadeGPUCommandContext.js";
|
|
3
|
-
import { GPUDatabase } from "../buffer/table/GPUDatabase.js";
|
|
4
|
-
import { GPUSceneShadowmapContext } from "../shadow/map/GPUSceneShadowmapContext.js";
|
|
5
|
-
import { GPUTextureContext } from "../texture/GPUTextureContext.js";
|
|
6
|
-
import {
|
|
7
|
-
import { texture_write_to_gpu } from "../texture/texture_write_to_gpu.js";
|
|
8
|
-
import { execute_filter_environment_map } from "./environment/execute_filter_environment_map.js";
|
|
9
|
-
import { LIGHT_DATABASE_SPEC } from "./LIGHT_DATABASE_SPEC.js";
|
|
10
|
-
import { light_record_directional } from "./model/io/light_record_directional.js";
|
|
11
|
-
import { light_record_point } from "./model/io/light_record_point.js";
|
|
12
|
-
import { light_record_spot } from "./model/io/light_record_spot.js";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Directional-light cap. Sized so the directional occupancy bitmap
|
|
16
|
-
* fits in a single u32, which is what
|
|
17
|
-
* {@link chunk_directional_lights_iteration_mask} reads. Writing past
|
|
18
|
-
* key 31 would silently drop the light from iteration; {@link #build}
|
|
19
|
-
* warns once per build when this happens.
|
|
20
|
-
*
|
|
21
|
-
* Point and spot lights have no analogous cap — their consumers walk
|
|
22
|
-
* the full per-page bitmap, so any number of point/spot lights
|
|
23
|
-
* iterate correctly (e.g. clustered rendering routinely deals in
|
|
24
|
-
* hundreds).
|
|
25
|
-
*
|
|
26
|
-
* @type {number}
|
|
27
|
-
*/
|
|
28
|
-
const MAX_DIRECTIONAL_LIGHTS = 32;
|
|
29
|
-
|
|
30
|
-
export class GPULightCollection {
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @type {LightCollection}
|
|
34
|
-
*/
|
|
35
|
-
#source
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
39
|
-
* @returns {LightCollection}
|
|
40
|
-
*/
|
|
41
|
-
get source() {
|
|
42
|
-
return this.#source;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @type {GPUDevice}
|
|
47
|
-
*/
|
|
48
|
-
#device
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Backing GPUDatabase for the per-type light tables (point, spot, directional)
|
|
52
|
-
* and shadowmap regions. Layout is defined by {@link LIGHT_DATABASE_SPEC}.
|
|
53
|
-
*
|
|
54
|
-
* @type {GPUDatabase}
|
|
55
|
-
*/
|
|
56
|
-
#database;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* @returns {GPUDatabase}
|
|
60
|
-
*/
|
|
61
|
-
get database() {
|
|
62
|
-
return this.#database;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* The single GPU buffer that backs the database. Bind this as `array<u32>` in
|
|
67
|
-
* shaders that need to read light records via the auto-generated
|
|
68
|
-
* {@link GPUTypedTableDescriptor.chunk_read} helpers.
|
|
69
|
-
*
|
|
70
|
-
* @returns {GPUBuffer}
|
|
71
|
-
*/
|
|
72
|
-
get buffer_data() {
|
|
73
|
-
return this.#database.buffer;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Per-scene shadow allocator + rasterizer, owned by this collection because the
|
|
78
|
-
* shadow records live in the same database (shadow_point / shadow_spot /
|
|
79
|
-
* shadow_directional tables) and the per-light `shadow_id` field is the index into
|
|
80
|
-
* those tables. Lifecycle, update, and destruction are all chained off this object.
|
|
81
|
-
* @type {GPUSceneShadowmapContext}
|
|
82
|
-
*/
|
|
83
|
-
#shadow_context;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* @returns {GPUSceneShadowmapContext}
|
|
87
|
-
*/
|
|
88
|
-
get shadow_context() {
|
|
89
|
-
return this.#shadow_context;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
*
|
|
94
|
-
* @type {number}
|
|
95
|
-
*/
|
|
96
|
-
#committed_version = -1;
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Per-type counts written in the previous {@link build} pass. Used to identify
|
|
100
|
-
* the trailing slot range that must be removed to keep each table tightly packed.
|
|
101
|
-
*/
|
|
102
|
-
#prev_point_count = 0;
|
|
103
|
-
#prev_spot_count = 0;
|
|
104
|
-
#prev_directional_count = 0;
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Octahedral encoded texture, convolved
|
|
108
|
-
* see {@link LightCollection.environment}
|
|
109
|
-
* @type {GPUTextureContext}
|
|
110
|
-
*/
|
|
111
|
-
#environment;
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* @type {ShadeTexture}
|
|
115
|
-
*/
|
|
116
|
-
#environment_source;
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
*
|
|
121
|
-
* @returns {GPUTextureContext}
|
|
122
|
-
*/
|
|
123
|
-
get environment() {
|
|
124
|
-
return this.#environment;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
get gpu_memory_usage() {
|
|
129
|
-
return this.#environment.gpu_memory_usage
|
|
130
|
-
+ this.#database.gpu_memory_usage
|
|
131
|
-
;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
*
|
|
136
|
-
* @param {GraphicsContext} graphics
|
|
137
|
-
* @param {GPUSceneContext} scene_ctx the GPU-side context for this scene; the shadow
|
|
138
|
-
* context constructs its own ViewManager that needs to look up this same context
|
|
139
|
-
* when materializing GPUViewContexts for shadow views.
|
|
140
|
-
*/
|
|
141
|
-
constructor(graphics, scene_ctx) {
|
|
142
|
-
assert.defined(graphics, 'graphics');
|
|
143
|
-
assert.defined(scene_ctx, 'scene_ctx');
|
|
144
|
-
assert.equal(scene_ctx.isGPUSceneContext, true, 'scene_ctx.isGPUSceneContext !== true');
|
|
145
|
-
|
|
146
|
-
const scene = scene_ctx.scene;
|
|
147
|
-
const device = graphics.device;
|
|
148
|
-
|
|
149
|
-
this.#device = device;
|
|
150
|
-
this.#source = scene.lights;
|
|
151
|
-
|
|
152
|
-
this.#environment = new GPUTextureContext(this.#device);
|
|
153
|
-
this.#environment.descriptor.label = "environment map";
|
|
154
|
-
this.#environment.descriptor.format = "rgba16float";
|
|
155
|
-
this.#environment.descriptor.usage |=
|
|
156
|
-
GPUTextureUsage.COPY_DST // so we can write to it
|
|
157
|
-
| GPUTextureUsage.STORAGE_BINDING // so we can convolve it in compute shader
|
|
158
|
-
;
|
|
159
|
-
|
|
160
|
-
this.#database = new GPUDatabase({
|
|
161
|
-
device,
|
|
162
|
-
label: 'Light Collection / Database',
|
|
163
|
-
definition: LIGHT_DATABASE_SPEC,
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
this.#shadow_context = new GPUSceneShadowmapContext(graphics, scene_ctx, this);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
*
|
|
171
|
-
* @param {GraphicsContext} ctx
|
|
172
|
-
*/
|
|
173
|
-
#update_environment(ctx) {
|
|
174
|
-
const source_env = this.#source.environment;
|
|
175
|
-
|
|
176
|
-
if (this.#environment_source === source_env) {
|
|
177
|
-
// assume up-to-date
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
this.#environment_source = source_env;
|
|
182
|
-
|
|
183
|
-
const gpu_ctx = this.#environment;
|
|
184
|
-
|
|
185
|
-
const source_image = source_env.image;
|
|
186
|
-
gpu_ctx.resize(source_image.width, source_image.height);
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
this.#
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
this.#
|
|
311
|
-
this.#
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
1
|
+
import { assert } from "../../../core/assert.js";
|
|
2
|
+
import { ShadeGPUCommandContext } from "../../device/ShadeGPUCommandContext.js";
|
|
3
|
+
import { GPUDatabase } from "../buffer/table/GPUDatabase.js";
|
|
4
|
+
import { GPUSceneShadowmapContext } from "../shadow/map/GPUSceneShadowmapContext.js";
|
|
5
|
+
import { GPUTextureContext } from "../texture/GPUTextureContext.js";
|
|
6
|
+
import { texture_mip_level_count } from "../../util/texture_mip_extent.js";
|
|
7
|
+
import { texture_write_to_gpu } from "../texture/texture_write_to_gpu.js";
|
|
8
|
+
import { execute_filter_environment_map } from "./environment/execute_filter_environment_map.js";
|
|
9
|
+
import { LIGHT_DATABASE_SPEC } from "./LIGHT_DATABASE_SPEC.js";
|
|
10
|
+
import { light_record_directional } from "./model/io/light_record_directional.js";
|
|
11
|
+
import { light_record_point } from "./model/io/light_record_point.js";
|
|
12
|
+
import { light_record_spot } from "./model/io/light_record_spot.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Directional-light cap. Sized so the directional occupancy bitmap
|
|
16
|
+
* fits in a single u32, which is what
|
|
17
|
+
* {@link chunk_directional_lights_iteration_mask} reads. Writing past
|
|
18
|
+
* key 31 would silently drop the light from iteration; {@link #build}
|
|
19
|
+
* warns once per build when this happens.
|
|
20
|
+
*
|
|
21
|
+
* Point and spot lights have no analogous cap — their consumers walk
|
|
22
|
+
* the full per-page bitmap, so any number of point/spot lights
|
|
23
|
+
* iterate correctly (e.g. clustered rendering routinely deals in
|
|
24
|
+
* hundreds).
|
|
25
|
+
*
|
|
26
|
+
* @type {number}
|
|
27
|
+
*/
|
|
28
|
+
const MAX_DIRECTIONAL_LIGHTS = 32;
|
|
29
|
+
|
|
30
|
+
export class GPULightCollection {
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @type {LightCollection}
|
|
34
|
+
*/
|
|
35
|
+
#source
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
* @returns {LightCollection}
|
|
40
|
+
*/
|
|
41
|
+
get source() {
|
|
42
|
+
return this.#source;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @type {GPUDevice}
|
|
47
|
+
*/
|
|
48
|
+
#device
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Backing GPUDatabase for the per-type light tables (point, spot, directional)
|
|
52
|
+
* and shadowmap regions. Layout is defined by {@link LIGHT_DATABASE_SPEC}.
|
|
53
|
+
*
|
|
54
|
+
* @type {GPUDatabase}
|
|
55
|
+
*/
|
|
56
|
+
#database;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @returns {GPUDatabase}
|
|
60
|
+
*/
|
|
61
|
+
get database() {
|
|
62
|
+
return this.#database;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The single GPU buffer that backs the database. Bind this as `array<u32>` in
|
|
67
|
+
* shaders that need to read light records via the auto-generated
|
|
68
|
+
* {@link GPUTypedTableDescriptor.chunk_read} helpers.
|
|
69
|
+
*
|
|
70
|
+
* @returns {GPUBuffer}
|
|
71
|
+
*/
|
|
72
|
+
get buffer_data() {
|
|
73
|
+
return this.#database.buffer;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Per-scene shadow allocator + rasterizer, owned by this collection because the
|
|
78
|
+
* shadow records live in the same database (shadow_point / shadow_spot /
|
|
79
|
+
* shadow_directional tables) and the per-light `shadow_id` field is the index into
|
|
80
|
+
* those tables. Lifecycle, update, and destruction are all chained off this object.
|
|
81
|
+
* @type {GPUSceneShadowmapContext}
|
|
82
|
+
*/
|
|
83
|
+
#shadow_context;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @returns {GPUSceneShadowmapContext}
|
|
87
|
+
*/
|
|
88
|
+
get shadow_context() {
|
|
89
|
+
return this.#shadow_context;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
*
|
|
94
|
+
* @type {number}
|
|
95
|
+
*/
|
|
96
|
+
#committed_version = -1;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Per-type counts written in the previous {@link build} pass. Used to identify
|
|
100
|
+
* the trailing slot range that must be removed to keep each table tightly packed.
|
|
101
|
+
*/
|
|
102
|
+
#prev_point_count = 0;
|
|
103
|
+
#prev_spot_count = 0;
|
|
104
|
+
#prev_directional_count = 0;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Octahedral encoded texture, convolved
|
|
108
|
+
* see {@link LightCollection.environment}
|
|
109
|
+
* @type {GPUTextureContext}
|
|
110
|
+
*/
|
|
111
|
+
#environment;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @type {ShadeTexture}
|
|
115
|
+
*/
|
|
116
|
+
#environment_source;
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
*
|
|
121
|
+
* @returns {GPUTextureContext}
|
|
122
|
+
*/
|
|
123
|
+
get environment() {
|
|
124
|
+
return this.#environment;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
get gpu_memory_usage() {
|
|
129
|
+
return this.#environment.gpu_memory_usage
|
|
130
|
+
+ this.#database.gpu_memory_usage
|
|
131
|
+
;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
*
|
|
136
|
+
* @param {GraphicsContext} graphics
|
|
137
|
+
* @param {GPUSceneContext} scene_ctx the GPU-side context for this scene; the shadow
|
|
138
|
+
* context constructs its own ViewManager that needs to look up this same context
|
|
139
|
+
* when materializing GPUViewContexts for shadow views.
|
|
140
|
+
*/
|
|
141
|
+
constructor(graphics, scene_ctx) {
|
|
142
|
+
assert.defined(graphics, 'graphics');
|
|
143
|
+
assert.defined(scene_ctx, 'scene_ctx');
|
|
144
|
+
assert.equal(scene_ctx.isGPUSceneContext, true, 'scene_ctx.isGPUSceneContext !== true');
|
|
145
|
+
|
|
146
|
+
const scene = scene_ctx.scene;
|
|
147
|
+
const device = graphics.device;
|
|
148
|
+
|
|
149
|
+
this.#device = device;
|
|
150
|
+
this.#source = scene.lights;
|
|
151
|
+
|
|
152
|
+
this.#environment = new GPUTextureContext(this.#device);
|
|
153
|
+
this.#environment.descriptor.label = "environment map";
|
|
154
|
+
this.#environment.descriptor.format = "rgba16float";
|
|
155
|
+
this.#environment.descriptor.usage |=
|
|
156
|
+
GPUTextureUsage.COPY_DST // so we can write to it
|
|
157
|
+
| GPUTextureUsage.STORAGE_BINDING // so we can convolve it in compute shader
|
|
158
|
+
;
|
|
159
|
+
|
|
160
|
+
this.#database = new GPUDatabase({
|
|
161
|
+
device,
|
|
162
|
+
label: 'Light Collection / Database',
|
|
163
|
+
definition: LIGHT_DATABASE_SPEC,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
this.#shadow_context = new GPUSceneShadowmapContext(graphics, scene_ctx, this);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
*
|
|
171
|
+
* @param {GraphicsContext} ctx
|
|
172
|
+
*/
|
|
173
|
+
#update_environment(ctx) {
|
|
174
|
+
const source_env = this.#source.environment;
|
|
175
|
+
|
|
176
|
+
if (this.#environment_source === source_env) {
|
|
177
|
+
// assume up-to-date
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
this.#environment_source = source_env;
|
|
182
|
+
|
|
183
|
+
const gpu_ctx = this.#environment;
|
|
184
|
+
|
|
185
|
+
const source_image = source_env.image;
|
|
186
|
+
gpu_ctx.resize(source_image.width, source_image.height);
|
|
187
|
+
/*
|
|
188
|
+
The environment map is equirectangular and this context is built 2D a few lines up — the
|
|
189
|
+
descriptor keeps the default dimension and `resize` above only takes two axes. Asked of the
|
|
190
|
+
descriptor rather than assumed, so the count follows if that ever stops being true.
|
|
191
|
+
*/
|
|
192
|
+
const gpu_size = gpu_ctx.descriptor.size;
|
|
193
|
+
|
|
194
|
+
gpu_ctx.descriptor.mipLevelCount = texture_mip_level_count(
|
|
195
|
+
gpu_size.width, gpu_size.height, gpu_size.depthOrArrayLayers, gpu_ctx.descriptor.dimension
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
gpu_ctx.allocate();
|
|
199
|
+
|
|
200
|
+
if (
|
|
201
|
+
source_image.source instanceof ImageBitmap
|
|
202
|
+
&& (gpu_ctx.descriptor.usage & GPUTextureUsage.RENDER_ATTACHMENT) === 0
|
|
203
|
+
) {
|
|
204
|
+
// need RENDER_ATTACHMENT to use GPUQueue.copyExternalImageToTexture API
|
|
205
|
+
// update descriptor and re-allocate texture
|
|
206
|
+
gpu_ctx.descriptor.usage |= GPUTextureUsage.RENDER_ATTACHMENT;
|
|
207
|
+
gpu_ctx.allocate(false);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
texture_write_to_gpu(source_image, gpu_ctx.gpu_texture, this.#device.queue, source_image.level_count);
|
|
211
|
+
|
|
212
|
+
// convolve
|
|
213
|
+
const cmd = ShadeGPUCommandContext.create(ctx);
|
|
214
|
+
|
|
215
|
+
execute_filter_environment_map(gpu_ctx, cmd);
|
|
216
|
+
|
|
217
|
+
cmd.finish();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
*
|
|
222
|
+
* @param {GraphicsContext} ctx
|
|
223
|
+
*/
|
|
224
|
+
update(ctx) {
|
|
225
|
+
assert.defined(ctx, 'ctx');
|
|
226
|
+
|
|
227
|
+
this.#update_environment(ctx);
|
|
228
|
+
|
|
229
|
+
// Reconcile shadow allocations against the current scene every frame, even when
|
|
230
|
+
// {@link LightCollection.version} hasn't moved. Shadow allocations can shift on
|
|
231
|
+
// changes that don't bump version (e.g. flipping `light.casts_shadow`), and the
|
|
232
|
+
// `shadow_id` we stamp into each light record depends on this allocation. When
|
|
233
|
+
// process_lights touches anything we mark the source dirty so the build below
|
|
234
|
+
// re-publishes those records.
|
|
235
|
+
if (this.#shadow_context.process_lights()) {
|
|
236
|
+
this.#source.needsUpdate = true;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (this.#committed_version === this.#source.version) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const cmd = ShadeGPUCommandContext.create(ctx, 'GPULightCollection/build');
|
|
244
|
+
|
|
245
|
+
this.#build(cmd);
|
|
246
|
+
|
|
247
|
+
cmd.finish();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Marshal source lights into the per-type database tables, keeping each table
|
|
252
|
+
* tightly packed in the index range [0, type_count).
|
|
253
|
+
*
|
|
254
|
+
* @param {ShadeGPUCommandContext} cmd
|
|
255
|
+
*/
|
|
256
|
+
#build(cmd) {
|
|
257
|
+
const lights = this.#source.elements;
|
|
258
|
+
|
|
259
|
+
const table_point = this.#database.get('light_point');
|
|
260
|
+
const table_spot = this.#database.get('light_spot');
|
|
261
|
+
const table_directional = this.#database.get('light_directional');
|
|
262
|
+
|
|
263
|
+
let point_count = 0;
|
|
264
|
+
let spot_count = 0;
|
|
265
|
+
let directional_count = 0;
|
|
266
|
+
|
|
267
|
+
// Directional only — silently dropping a directional light
|
|
268
|
+
// would surface as a missing visual; flagging keeps consumers
|
|
269
|
+
// iterating only the first bitmap word correct for whatever
|
|
270
|
+
// did fit. Point and spot have no cap.
|
|
271
|
+
let directional_overflow_warned = false;
|
|
272
|
+
|
|
273
|
+
for (let i = 0; i < lights.length; i++) {
|
|
274
|
+
const light = lights[i];
|
|
275
|
+
|
|
276
|
+
if (light.isPointLight === true) {
|
|
277
|
+
table_point.set(point_count, light_record_point(light));
|
|
278
|
+
point_count++;
|
|
279
|
+
} else if (light.isDirectionalLight === true) {
|
|
280
|
+
if (directional_count >= MAX_DIRECTIONAL_LIGHTS) {
|
|
281
|
+
if (!directional_overflow_warned) {
|
|
282
|
+
console.warn(
|
|
283
|
+
`GPULightCollection: directional light count exceeds MAX_DIRECTIONAL_LIGHTS (${MAX_DIRECTIONAL_LIGHTS}); extras will not be written to the database.`
|
|
284
|
+
);
|
|
285
|
+
directional_overflow_warned = true;
|
|
286
|
+
}
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
table_directional.set(directional_count, light_record_directional(light));
|
|
290
|
+
directional_count++;
|
|
291
|
+
} else if (light.isSpotLight === true) {
|
|
292
|
+
table_spot.set(spot_count, light_record_spot(light));
|
|
293
|
+
spot_count++;
|
|
294
|
+
}
|
|
295
|
+
// unrecognized light kinds are silently dropped
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// trim trailing slots from previous build to keep each table tightly packed
|
|
299
|
+
for (let i = point_count; i < this.#prev_point_count; i++) {
|
|
300
|
+
table_point.remove(i);
|
|
301
|
+
}
|
|
302
|
+
for (let i = spot_count; i < this.#prev_spot_count; i++) {
|
|
303
|
+
table_spot.remove(i);
|
|
304
|
+
}
|
|
305
|
+
for (let i = directional_count; i < this.#prev_directional_count; i++) {
|
|
306
|
+
table_directional.remove(i);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
this.#prev_point_count = point_count;
|
|
310
|
+
this.#prev_spot_count = spot_count;
|
|
311
|
+
this.#prev_directional_count = directional_count;
|
|
312
|
+
|
|
313
|
+
this.#database.update(cmd);
|
|
314
|
+
|
|
315
|
+
this.#committed_version = this.#source.version;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
destroy() {
|
|
319
|
+
this.#shadow_context.destroy();
|
|
320
|
+
this.#database.destroy();
|
|
321
|
+
this.#environment.destroy();
|
|
322
|
+
}
|
|
323
|
+
}
|