@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
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { BinaryDataType } from "../../../../core/binary/type/BinaryDataType.js";
|
|
2
|
+
import { isImageBitmap } from "../../../../core/dom/isImageBitmap.js";
|
|
3
|
+
import { ColorSpace } from "../ColorSpace.js";
|
|
4
|
+
import { infer_format_from_parameters } from "./infer_format_from_parameters.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The {@link GPUTextureFormat} a {@link ShadeImage}'s texels are in.
|
|
8
|
+
*
|
|
9
|
+
* A free function rather than a getter on the image, because {@link ShadeImage} describes *data* —
|
|
10
|
+
* a channel count, a data type, a colour space, some bytes — and what WebGPU calls that arrangement
|
|
11
|
+
* is not the data's business. The image stays a model the encoder, the container readers and the
|
|
12
|
+
* asset pipeline can hold without any of them importing a graphics API.
|
|
13
|
+
*
|
|
14
|
+
* What this replaces is the same inference run at *upload* time, inside the descriptor builder. The
|
|
15
|
+
* move matters more than the mechanism: a format worked out by inspecting pixels is a question
|
|
16
|
+
* block-compressed texels cannot answer, so a {@link ShadeTexelData} states its format instead and
|
|
17
|
+
* this function simply reports it. That is what lets both kinds share one path.
|
|
18
|
+
*
|
|
19
|
+
* **Not cached anywhere.** `color_space` is assigned *after* construction in nine places
|
|
20
|
+
* (`gltf_create_material` among them), so a format captured once would leave every glTF albedo map
|
|
21
|
+
* on `rgba8unorm` and silently drop its sRGB decode.
|
|
22
|
+
*
|
|
23
|
+
* @param {ShadeImage} image
|
|
24
|
+
* @returns {GPUTextureFormat}
|
|
25
|
+
* @throws {Error} if the image has no source, or one this does not recognise — a format guessed for
|
|
26
|
+
* texels nobody can describe would put the wrong number of bytes on both sides of the upload
|
|
27
|
+
*/
|
|
28
|
+
export function texture_format_from_shade_image(image) {
|
|
29
|
+
const source = image.source;
|
|
30
|
+
|
|
31
|
+
if (source === undefined || source === null) {
|
|
32
|
+
throw new Error(`image ${image.id} has no source, so no format`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (source.isShadeTexelData === true) {
|
|
36
|
+
// already in a GPU format; it says which
|
|
37
|
+
return source.format;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (source.isSampler2D === true) {
|
|
41
|
+
return infer_format_from_parameters(
|
|
42
|
+
image.channel_count, image.data_type, image.normalized, image.color_space
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (isImageBitmap(source)) {
|
|
47
|
+
/*
|
|
48
|
+
A bitmap is whatever the browser decoded it to, which is 8-bit RGBA — the channel count and
|
|
49
|
+
data type the image carries describe the file, not the decode.
|
|
50
|
+
*/
|
|
51
|
+
if (image.data_type === BinaryDataType.Float16) {
|
|
52
|
+
return "rgba16float";
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (image.color_space === ColorSpace.SRGB) {
|
|
56
|
+
// sampling decodes sRGB to linear for free
|
|
57
|
+
// @see https://www.w3.org/TR/webgpu/#texture-formats
|
|
58
|
+
return "rgba8unorm-srgb";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return "rgba8unorm";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (source instanceof ArrayBuffer) {
|
|
65
|
+
return infer_format_from_parameters(
|
|
66
|
+
image.channel_count, image.data_type, image.normalized, image.color_space
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
throw new Error(`Unsupported image data`);
|
|
71
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The formats this engine would choose for `role`, best first, filtered to what the device can
|
|
3
|
+
* sample.
|
|
4
|
+
*
|
|
5
|
+
* This is the whole of the engine's part in choosing an encoding. It answers *what would be good*;
|
|
6
|
+
* it does not fetch, does not know what was actually built for a given texture, and does not fall
|
|
7
|
+
* back — all of which belong to the asset layer, which turns an entry into a request and reaches for
|
|
8
|
+
* an uncompressed encoding when none of these can be had.
|
|
9
|
+
*
|
|
10
|
+
* **Names are the non-srgb ones.** `bc7-rgba-unorm` and `bc7-rgba-unorm-srgb` are the same bytes, so
|
|
11
|
+
* srgb-ness is not a property of the encoding to be chosen here — it is picked when the texture is
|
|
12
|
+
* created, from the image's colour space.
|
|
13
|
+
*
|
|
14
|
+
* @param {TextureRole|number} role
|
|
15
|
+
* @param {Set<GPUTextureFormat>} support what this device can sample — see
|
|
16
|
+
* {@link gpu_texture_compression_support}
|
|
17
|
+
* @returns {GPUTextureFormat[]} best first; empty when the device can sample none of them, which is
|
|
18
|
+
* an ordinary answer and means "ask for the uncompressed encoding"
|
|
19
|
+
*/
|
|
20
|
+
export function texture_format_preference(role: TextureRole | number, support: Set<GPUTextureFormat>): GPUTextureFormat[];
|
|
21
|
+
import { TextureRole } from "../TextureRole.js";
|
|
22
|
+
//# sourceMappingURL=texture_format_preference.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"texture_format_preference.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/texture/format/texture_format_preference.js"],"names":[],"mappings":"AA8DA;;;;;;;;;;;;;;;;;;GAkBG;AACH,gDANW,WAAW,GAAC,MAAM,WAClB,qBAAqB,GAEnB,kBAAkB,CAU9B;4BAtF2B,mBAAmB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
import { TextureFormat } from "../../../descriptor/texture/format/TextureFormat.js";
|
|
3
|
+
import { TextureRole } from "../TextureRole.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Colour with alpha, best first. Albedo and emissive both want this.
|
|
7
|
+
*
|
|
8
|
+
* BC7 is the best quality-per-byte the desktop family offers for four channels; ASTC 4×4 matches its
|
|
9
|
+
* 8 bits per texel on mobile; ETC2's RGBA8 is the last resort for a device with neither.
|
|
10
|
+
*
|
|
11
|
+
* @type {GPUTextureFormat[]}
|
|
12
|
+
*/
|
|
13
|
+
const COLOR = [
|
|
14
|
+
TextureFormat.BC7_RGBA_UNORM,
|
|
15
|
+
TextureFormat.ASTC_4X4_UNORM,
|
|
16
|
+
TextureFormat.ETC2_RGBA8UNORM,
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Tangent-space normals, best first.
|
|
21
|
+
*
|
|
22
|
+
* **Two channels, wherever they can be had.** A tangent-space normal's Z is positive by construction,
|
|
23
|
+
* so {@link chunk_decode_tangent_normal} reconstructs it from XY and the blue channel of a normal map
|
|
24
|
+
* carries nothing. `bc5-rg-unorm` therefore spends on two channels the same 8 bits per texel that BC7
|
|
25
|
+
* spends on four, and `eac-rg11unorm` does the same with 11 bits per channel — both are dramatically
|
|
26
|
+
* better here than a colour codec, which is what makes BC1 or BC7 normals band visibly.
|
|
27
|
+
*
|
|
28
|
+
* ASTC has no two-channel format; its 4×4 block stores XY in RG and the decode ignores the rest.
|
|
29
|
+
*
|
|
30
|
+
* @type {GPUTextureFormat[]}
|
|
31
|
+
*/
|
|
32
|
+
const NORMAL = [
|
|
33
|
+
TextureFormat.BC5_RG_UNORM,
|
|
34
|
+
TextureFormat.ASTC_4X4_UNORM,
|
|
35
|
+
TextureFormat.EAC_RG11UNORM,
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Packed linear data — occlusion, roughness, metalness.
|
|
40
|
+
*
|
|
41
|
+
* The channels are independent quantities rather than a colour, so a codec's cross-channel
|
|
42
|
+
* correlation buys nothing; the reason to prefer BC7 anyway is that it spends its bits per channel
|
|
43
|
+
* rather than on a shared endpoint line, which is what BC1 gets wrong here.
|
|
44
|
+
*
|
|
45
|
+
* @type {GPUTextureFormat[]}
|
|
46
|
+
*/
|
|
47
|
+
const ORM = [
|
|
48
|
+
TextureFormat.BC7_RGBA_UNORM,
|
|
49
|
+
TextureFormat.ASTC_4X4_UNORM,
|
|
50
|
+
TextureFormat.ETC2_RGBA8UNORM,
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @type {Object<TextureRole, GPUTextureFormat[]>}
|
|
55
|
+
*/
|
|
56
|
+
const BY_ROLE = {
|
|
57
|
+
[TextureRole.Albedo]: COLOR,
|
|
58
|
+
[TextureRole.Emissive]: COLOR,
|
|
59
|
+
[TextureRole.Normal]: NORMAL,
|
|
60
|
+
[TextureRole.Orm]: ORM,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The formats this engine would choose for `role`, best first, filtered to what the device can
|
|
65
|
+
* sample.
|
|
66
|
+
*
|
|
67
|
+
* This is the whole of the engine's part in choosing an encoding. It answers *what would be good*;
|
|
68
|
+
* it does not fetch, does not know what was actually built for a given texture, and does not fall
|
|
69
|
+
* back — all of which belong to the asset layer, which turns an entry into a request and reaches for
|
|
70
|
+
* an uncompressed encoding when none of these can be had.
|
|
71
|
+
*
|
|
72
|
+
* **Names are the non-srgb ones.** `bc7-rgba-unorm` and `bc7-rgba-unorm-srgb` are the same bytes, so
|
|
73
|
+
* srgb-ness is not a property of the encoding to be chosen here — it is picked when the texture is
|
|
74
|
+
* created, from the image's colour space.
|
|
75
|
+
*
|
|
76
|
+
* @param {TextureRole|number} role
|
|
77
|
+
* @param {Set<GPUTextureFormat>} support what this device can sample — see
|
|
78
|
+
* {@link gpu_texture_compression_support}
|
|
79
|
+
* @returns {GPUTextureFormat[]} best first; empty when the device can sample none of them, which is
|
|
80
|
+
* an ordinary answer and means "ask for the uncompressed encoding"
|
|
81
|
+
*/
|
|
82
|
+
export function texture_format_preference(role, support) {
|
|
83
|
+
assert.enum(role, TextureRole, 'role');
|
|
84
|
+
assert.defined(support, 'support');
|
|
85
|
+
|
|
86
|
+
const preferred = BY_ROLE[role];
|
|
87
|
+
|
|
88
|
+
return preferred.filter(format => support.has(format));
|
|
89
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which encoding of a texture to fetch.
|
|
3
|
+
*
|
|
4
|
+
* The end of the chain {@link gpu_texture_compression_support} and {@link texture_format_preference}
|
|
5
|
+
* begin: what this device can sample, then what the engine would prefer for this kind of content,
|
|
6
|
+
* then — here — the best of those that somebody actually built.
|
|
7
|
+
*
|
|
8
|
+
* **Returns a path and nothing else.** Not the format it chose, because the caller does not need it:
|
|
9
|
+
* a reader determines a payload's format from the payload's own header, which is the only source
|
|
10
|
+
* that cannot be wrong. Handing back a format alongside would invite someone to trust the manifest
|
|
11
|
+
* over the bytes.
|
|
12
|
+
*
|
|
13
|
+
* **Always answers.** A device that supports no compression, or one whose preferred formats were
|
|
14
|
+
* never built, gets {@link TextureVariantSet.fallback} — the same path a tool or a test would ask
|
|
15
|
+
* for. There is no "nothing suitable" case for a caller to handle, because a texture with no
|
|
16
|
+
* universally readable encoding is a broken manifest rather than a runtime condition.
|
|
17
|
+
*
|
|
18
|
+
* @param {TextureVariantSet} variants what was built for this texture
|
|
19
|
+
* @param {TextureRole|number} role what the texture is for
|
|
20
|
+
* @param {Set<GPUTextureFormat>} support what this device can sample
|
|
21
|
+
* @returns {string} the path to fetch
|
|
22
|
+
*/
|
|
23
|
+
export function texture_variant_select(variants: TextureVariantSet, role: TextureRole | number, support: Set<GPUTextureFormat>): string;
|
|
24
|
+
//# sourceMappingURL=texture_variant_select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"texture_variant_select.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/texture/format/texture_variant_select.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,0EAJW,cAAY,MAAM,WAClB,qBAAqB,GACnB,MAAM,CAclB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
import { texture_format_preference } from "./texture_format_preference.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Which encoding of a texture to fetch.
|
|
6
|
+
*
|
|
7
|
+
* The end of the chain {@link gpu_texture_compression_support} and {@link texture_format_preference}
|
|
8
|
+
* begin: what this device can sample, then what the engine would prefer for this kind of content,
|
|
9
|
+
* then — here — the best of those that somebody actually built.
|
|
10
|
+
*
|
|
11
|
+
* **Returns a path and nothing else.** Not the format it chose, because the caller does not need it:
|
|
12
|
+
* a reader determines a payload's format from the payload's own header, which is the only source
|
|
13
|
+
* that cannot be wrong. Handing back a format alongside would invite someone to trust the manifest
|
|
14
|
+
* over the bytes.
|
|
15
|
+
*
|
|
16
|
+
* **Always answers.** A device that supports no compression, or one whose preferred formats were
|
|
17
|
+
* never built, gets {@link TextureVariantSet.fallback} — the same path a tool or a test would ask
|
|
18
|
+
* for. There is no "nothing suitable" case for a caller to handle, because a texture with no
|
|
19
|
+
* universally readable encoding is a broken manifest rather than a runtime condition.
|
|
20
|
+
*
|
|
21
|
+
* @param {TextureVariantSet} variants what was built for this texture
|
|
22
|
+
* @param {TextureRole|number} role what the texture is for
|
|
23
|
+
* @param {Set<GPUTextureFormat>} support what this device can sample
|
|
24
|
+
* @returns {string} the path to fetch
|
|
25
|
+
*/
|
|
26
|
+
export function texture_variant_select(variants, role, support) {
|
|
27
|
+
assert.defined(variants, 'variants');
|
|
28
|
+
|
|
29
|
+
for (const format of texture_format_preference(role, support)) {
|
|
30
|
+
const path = variants.path(format);
|
|
31
|
+
|
|
32
|
+
if (path !== undefined) {
|
|
33
|
+
return path;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return variants.fallback;
|
|
38
|
+
}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* If returns false - it means texture definitely has no alpha channel.
|
|
2
|
+
* If this returns false - it means the texture definitely has no alpha channel.
|
|
3
|
+
*
|
|
4
|
+
* Answered from the format, which knows exactly, rather than from the shape of whatever produced it.
|
|
5
|
+
* The previous version guessed from a `Sampler2D`'s `itemSize` and defaulted to `true` for everything
|
|
6
|
+
* else, so a single-channel `ArrayBuffer` image read as possibly-transparent.
|
|
7
|
+
*
|
|
8
|
+
* A false answer is a promise; a true one is only "cannot rule it out". Callers use this to skip
|
|
9
|
+
* alpha handling, so being wrong in the true direction costs a little work and being wrong in the
|
|
10
|
+
* false direction costs correctness.
|
|
3
11
|
*
|
|
4
12
|
* @param {ShadeTexture} texture
|
|
5
13
|
* @returns {boolean}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shade_texture_might_have_alpha.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/texture/shade_texture_might_have_alpha.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shade_texture_might_have_alpha.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/texture/shade_texture_might_have_alpha.js"],"names":[],"mappings":"AA2BA;;;;;;;;;;;;;GAaG;AACH,uEAFa,OAAO,CAmDnB"}
|
|
@@ -1,5 +1,40 @@
|
|
|
1
|
+
import { gpu_texture_format_info } from "../../descriptor/texture/format/gpu_texture_format_info.js";
|
|
2
|
+
import { texture_format_from_shade_image } from "./format/texture_format_from_shade_image.js";
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
|
-
*
|
|
5
|
+
* Compressed formats with no alpha channel at all.
|
|
6
|
+
*
|
|
7
|
+
* Everything else in the BC/ETC2/ASTC families either carries alpha or may — including
|
|
8
|
+
* `bc1-rgba-unorm`, which WebGPU exposes only in its RGBA spelling and which decodes one bit of
|
|
9
|
+
* punch-through alpha. Reading BC1 as opaque is the mistake this set exists to not make.
|
|
10
|
+
*
|
|
11
|
+
* @type {Set<GPUTextureFormat>}
|
|
12
|
+
*/
|
|
13
|
+
const NO_ALPHA_COMPRESSED = new Set([
|
|
14
|
+
"bc4-r-unorm",
|
|
15
|
+
"bc4-r-snorm",
|
|
16
|
+
"bc5-rg-unorm",
|
|
17
|
+
"bc5-rg-snorm",
|
|
18
|
+
"bc6h-rgb-ufloat",
|
|
19
|
+
"bc6h-rgb-float",
|
|
20
|
+
"etc2-rgb8unorm",
|
|
21
|
+
"etc2-rgb8unorm-srgb",
|
|
22
|
+
"eac-r11unorm",
|
|
23
|
+
"eac-r11snorm",
|
|
24
|
+
"eac-rg11unorm",
|
|
25
|
+
"eac-rg11snorm",
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* If this returns false - it means the texture definitely has no alpha channel.
|
|
30
|
+
*
|
|
31
|
+
* Answered from the format, which knows exactly, rather than from the shape of whatever produced it.
|
|
32
|
+
* The previous version guessed from a `Sampler2D`'s `itemSize` and defaulted to `true` for everything
|
|
33
|
+
* else, so a single-channel `ArrayBuffer` image read as possibly-transparent.
|
|
34
|
+
*
|
|
35
|
+
* A false answer is a promise; a true one is only "cannot rule it out". Callers use this to skip
|
|
36
|
+
* alpha handling, so being wrong in the true direction costs a little work and being wrong in the
|
|
37
|
+
* false direction costs correctness.
|
|
3
38
|
*
|
|
4
39
|
* @param {ShadeTexture} texture
|
|
5
40
|
* @returns {boolean}
|
|
@@ -9,18 +44,48 @@ export function shade_texture_might_have_alpha(texture) {
|
|
|
9
44
|
return false;
|
|
10
45
|
}
|
|
11
46
|
|
|
12
|
-
const
|
|
47
|
+
const image = texture.image;
|
|
48
|
+
|
|
49
|
+
if (image === undefined || image === null || image.source === undefined || image.source === null) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const source = image.source;
|
|
13
54
|
|
|
14
|
-
if (source
|
|
55
|
+
if (source.isShadeTexelData !== true && image.channel_count < 4) {
|
|
56
|
+
/*
|
|
57
|
+
Loose pixels with fewer than four channels. The *texture* will have an alpha channel — the
|
|
58
|
+
upload pads RGB to RGBA, because WebGPU has no three-channel format — but it is 1 everywhere
|
|
59
|
+
and the content has no transparency to speak of. Answering from the padded format would call
|
|
60
|
+
every opaque RGB image possibly-transparent.
|
|
61
|
+
|
|
62
|
+
Not asked of a texel payload: its channel count describes nothing, because whatever encoded
|
|
63
|
+
it already chose a format that says how many channels there are.
|
|
64
|
+
*/
|
|
15
65
|
return false;
|
|
16
66
|
}
|
|
17
67
|
|
|
18
|
-
|
|
68
|
+
let format;
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
format = texture_format_from_shade_image(image);
|
|
72
|
+
} catch {
|
|
73
|
+
// a source nothing can name a format for; no basis to promise there is no alpha
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (NO_ALPHA_COMPRESSED.has(format)) {
|
|
19
78
|
return false;
|
|
20
79
|
}
|
|
21
80
|
|
|
22
|
-
|
|
81
|
+
const info = gpu_texture_format_info(format);
|
|
82
|
+
|
|
83
|
+
if (info.block_width !== 1 || info.block_height !== 1) {
|
|
84
|
+
// a compressed format that is not in the set above — BC7, BC1's punch-through, ETC2's
|
|
85
|
+
// RGBA and RGB8A1, every ASTC block size
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
23
88
|
|
|
24
|
-
//
|
|
25
|
-
return
|
|
26
|
-
}
|
|
89
|
+
// uncompressed: the channel count is in the name, and only a four-channel format has an alpha
|
|
90
|
+
return /^(rgba|bgra)/.test(format);
|
|
91
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a texture's fourth channel means, and therefore what may be done to it.
|
|
3
|
+
*
|
|
4
|
+
* The renderer wants premultiplied alpha
|
|
5
|
+
* (@see https://www.realtimerendering.com/blog/gpus-prefer-premultiplication/), so an upload may have
|
|
6
|
+
* to multiply RGB by A on the way. Whether that is correct is not a property of the channel existing
|
|
7
|
+
* — it is a property of the channel *meaning opacity*. Scaling a height field, an ORM map or a LUT
|
|
8
|
+
* by its fourth channel corrupts it.
|
|
9
|
+
*
|
|
10
|
+
* Three answers rather than a boolean, because collapsing {@link Opaque } into {@link Straight } does
|
|
11
|
+
* exactly that corruption, and collapsing it into {@link Premultiplied } lies about data that was
|
|
12
|
+
* never multiplied by anything. Plus {@link Unspecified }, which is the *absence* of an answer and
|
|
13
|
+
* belongs in the enum rather than being spelled `undefined` alongside it — a field typed as this
|
|
14
|
+
* enum should only ever hold one of its members.
|
|
15
|
+
*
|
|
16
|
+
* Block-compressed data can only be {@link Premultiplied } or {@link Opaque }: nothing can multiply
|
|
17
|
+
* BC7 blocks without decoding them, so a compressed payload that declares {@link Straight } is a
|
|
18
|
+
* payload whose encoder did not do its job, and the upload says so rather than shipping fringes.
|
|
19
|
+
*/
|
|
20
|
+
export type AlphaMode = number;
|
|
21
|
+
export namespace AlphaMode {
|
|
22
|
+
let Unspecified: number;
|
|
23
|
+
let Opaque: number;
|
|
24
|
+
let Straight: number;
|
|
25
|
+
let Premultiplied: number;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=AlphaMode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AlphaMode.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/texture/source/AlphaMode.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;wBAmBU,MAAM"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a texture's fourth channel means, and therefore what may be done to it.
|
|
3
|
+
*
|
|
4
|
+
* The renderer wants premultiplied alpha
|
|
5
|
+
* (@see https://www.realtimerendering.com/blog/gpus-prefer-premultiplication/), so an upload may have
|
|
6
|
+
* to multiply RGB by A on the way. Whether that is correct is not a property of the channel existing
|
|
7
|
+
* — it is a property of the channel *meaning opacity*. Scaling a height field, an ORM map or a LUT
|
|
8
|
+
* by its fourth channel corrupts it.
|
|
9
|
+
*
|
|
10
|
+
* Three answers rather than a boolean, because collapsing {@link Opaque} into {@link Straight} does
|
|
11
|
+
* exactly that corruption, and collapsing it into {@link Premultiplied} lies about data that was
|
|
12
|
+
* never multiplied by anything. Plus {@link Unspecified}, which is the *absence* of an answer and
|
|
13
|
+
* belongs in the enum rather than being spelled `undefined` alongside it — a field typed as this
|
|
14
|
+
* enum should only ever hold one of its members.
|
|
15
|
+
*
|
|
16
|
+
* Block-compressed data can only be {@link Premultiplied} or {@link Opaque}: nothing can multiply
|
|
17
|
+
* BC7 blocks without decoding them, so a compressed payload that declares {@link Straight} is a
|
|
18
|
+
* payload whose encoder did not do its job, and the upload says so rather than shipping fringes.
|
|
19
|
+
*
|
|
20
|
+
* @enum {number}
|
|
21
|
+
*/
|
|
22
|
+
export const AlphaMode = {
|
|
23
|
+
/**
|
|
24
|
+
* Nothing has said. Derive it — see {@link ShadeImage.alpha_mode}.
|
|
25
|
+
*
|
|
26
|
+
* The state a field starts in, and the one to assign to go back to deriving after an override.
|
|
27
|
+
* A resolved alpha mode is never this: {@link ShadeImage.alpha_mode} answers one of the three
|
|
28
|
+
* below, always.
|
|
29
|
+
*/
|
|
30
|
+
Unspecified: 0,
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* There is no meaningful alpha. Never premultiply.
|
|
34
|
+
*
|
|
35
|
+
* The state of every non-colour texture: {@link ColorSpace.None} data, single- and two-channel
|
|
36
|
+
* images, anything whose fourth channel carries a value rather than an opacity.
|
|
37
|
+
*/
|
|
38
|
+
Opaque: 1,
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Colour with straight (unassociated) alpha — RGB is the colour at full opacity.
|
|
42
|
+
*
|
|
43
|
+
* Premultiplied on upload where that is possible, which for a block format it is not.
|
|
44
|
+
*/
|
|
45
|
+
Straight: 2,
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* RGB has already been multiplied by A, by an offline encoder or by
|
|
49
|
+
* `copyExternalImageToTexture`. Nothing further to do.
|
|
50
|
+
*/
|
|
51
|
+
Premultiplied: 3,
|
|
52
|
+
};
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
export class ShadeImage {
|
|
2
|
+
/**
|
|
3
|
+
* @param {ShadeTexelData} texel_data
|
|
4
|
+
* @returns {ShadeImage}
|
|
5
|
+
*/
|
|
6
|
+
static fromTexelData(texel_data: ShadeTexelData): ShadeImage;
|
|
2
7
|
/**
|
|
3
8
|
*
|
|
4
9
|
* @param {ImageBitmap} bitmap
|
|
@@ -58,6 +63,34 @@ export class ShadeImage {
|
|
|
58
63
|
get height(): number;
|
|
59
64
|
set depth(arg: number);
|
|
60
65
|
get depth(): number;
|
|
66
|
+
set alpha_mode(arg: number);
|
|
67
|
+
/**
|
|
68
|
+
* What this image's fourth channel means — see {@link AlphaMode}.
|
|
69
|
+
*
|
|
70
|
+
* {@link AlphaMode.Unspecified} — the state this starts in — means derive it from
|
|
71
|
+
* {@link color_space}. Derived rather than captured at construction because `color_space` is
|
|
72
|
+
* routinely assigned *after* the image is built: nine places do it, `shade_load_data_image` and
|
|
73
|
+
* `gltf_create_material` among them, and two of them assign {@link ColorSpace.None}. A value
|
|
74
|
+
* frozen at construction would describe the image nobody kept, and would premultiply exactly the
|
|
75
|
+
* data textures the {@link AlphaMode.Opaque} state exists to protect.
|
|
76
|
+
*
|
|
77
|
+
* The derivation is exactly the rule the upload path used to apply inline, so nothing changes
|
|
78
|
+
* for an image that says nothing: non-colour data is never premultiplied, colour is.
|
|
79
|
+
*
|
|
80
|
+
* Assigning {@link AlphaMode.Unspecified} goes back to deriving.
|
|
81
|
+
*
|
|
82
|
+
* @returns {AlphaMode|number} never {@link AlphaMode.Unspecified} — this resolves
|
|
83
|
+
*/
|
|
84
|
+
get alpha_mode(): number;
|
|
85
|
+
/**
|
|
86
|
+
* How many mip levels this image supplies.
|
|
87
|
+
*
|
|
88
|
+
* One, for everything that is not a {@link ShadeTexelData} — a bitmap or a sampler is a single
|
|
89
|
+
* level, and any others are generated.
|
|
90
|
+
*
|
|
91
|
+
* @returns {number}
|
|
92
|
+
*/
|
|
93
|
+
get level_count(): number;
|
|
61
94
|
hash(): number;
|
|
62
95
|
/**
|
|
63
96
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShadeImage.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/texture/source/ShadeImage.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ShadeImage.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/texture/source/ShadeImage.js"],"names":[],"mappings":"AAUA;IA6JI;;;OAGG;IACH,kDAFa,UAAU,CAetB;IAeD;;;;OAIG;IACH,+BAHW,WAAW,GACV,UAAU,CAkBrB;IAED;;;;OAIG;IACH,0CAFY,UAAU,CAqBrB;IAED;;;;;;;;;OASG;IACH,qCARW,WAAW,iBACX,MAAM,aACN,cAAc,UACd,MAAM,WACN,MAAM,UACN,MAAM,GACL,UAAU,CAkCrB;IAjRD,iBAEC;IAED;;;OAGG;IACH,aAFU,UAAU,GAAC,MAAM,CAES;IAgBpC,2BAEC;IAVD;;;OAGG;IACH,wBAEC;IAoBD,+BAEC;IAVD;;;OAGG;IACH,4BAEC;IAMD;;;;OAIG;IACH,YAFU,OAAO,CAEC;IAelB,qBAEC;IAVD;;;OAGG;IACH,kBAEC;IAYD,uBAEC;IAND,oBAEC;IAUD,wBAEC;IAND,qBAEC;IAUD,uBAEC;IAND,oBAEC;IAoCD,4BAIC;IA7BD;;;;;;;;;;;;;;;;OAgBG;IACH,yBAMC;IAQD;;;;;;;OAOG;IACH,0BAQC;IAqBD,eAEC;IAED;;;;OAIG;IACH,cAHW,UAAU,GACR,OAAO,CAInB;IAgGL;;;OAGG;IACH,uBAFU,OAAO,CAEgB;;CANhC;2BA9R0B,kBAAkB;+BAJd,gDAAgD"}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
compute_binary_data_type_from_typed_array
|
|
5
5
|
} from "../../../../core/collection/array/typed/compute_binary_data_type_from_typed_array.js";
|
|
6
6
|
import { ColorSpace } from "../ColorSpace.js";
|
|
7
|
+
import { AlphaMode } from "./AlphaMode.js";
|
|
7
8
|
|
|
8
9
|
let id_counter = 0;
|
|
9
10
|
|
|
@@ -110,6 +111,79 @@ export class ShadeImage {
|
|
|
110
111
|
this.#size[2] = value;
|
|
111
112
|
}
|
|
112
113
|
|
|
114
|
+
/**
|
|
115
|
+
* @type {AlphaMode|number}
|
|
116
|
+
*/
|
|
117
|
+
#alpha_mode = AlphaMode.Unspecified;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* What this image's fourth channel means — see {@link AlphaMode}.
|
|
121
|
+
*
|
|
122
|
+
* {@link AlphaMode.Unspecified} — the state this starts in — means derive it from
|
|
123
|
+
* {@link color_space}. Derived rather than captured at construction because `color_space` is
|
|
124
|
+
* routinely assigned *after* the image is built: nine places do it, `shade_load_data_image` and
|
|
125
|
+
* `gltf_create_material` among them, and two of them assign {@link ColorSpace.None}. A value
|
|
126
|
+
* frozen at construction would describe the image nobody kept, and would premultiply exactly the
|
|
127
|
+
* data textures the {@link AlphaMode.Opaque} state exists to protect.
|
|
128
|
+
*
|
|
129
|
+
* The derivation is exactly the rule the upload path used to apply inline, so nothing changes
|
|
130
|
+
* for an image that says nothing: non-colour data is never premultiplied, colour is.
|
|
131
|
+
*
|
|
132
|
+
* Assigning {@link AlphaMode.Unspecified} goes back to deriving.
|
|
133
|
+
*
|
|
134
|
+
* @returns {AlphaMode|number} never {@link AlphaMode.Unspecified} — this resolves
|
|
135
|
+
*/
|
|
136
|
+
get alpha_mode() {
|
|
137
|
+
if (this.#alpha_mode !== AlphaMode.Unspecified) {
|
|
138
|
+
return this.#alpha_mode;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return this.color_space === ColorSpace.None ? AlphaMode.Opaque : AlphaMode.Straight;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
set alpha_mode(value) {
|
|
145
|
+
assert.enum(value, AlphaMode, 'alpha_mode');
|
|
146
|
+
|
|
147
|
+
this.#alpha_mode = value;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* How many mip levels this image supplies.
|
|
152
|
+
*
|
|
153
|
+
* One, for everything that is not a {@link ShadeTexelData} — a bitmap or a sampler is a single
|
|
154
|
+
* level, and any others are generated.
|
|
155
|
+
*
|
|
156
|
+
* @returns {number}
|
|
157
|
+
*/
|
|
158
|
+
get level_count() {
|
|
159
|
+
const source = this.#source;
|
|
160
|
+
|
|
161
|
+
if (source !== undefined && source !== null && source.isShadeTexelData === true) {
|
|
162
|
+
return source.level_count;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return 1;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @param {ShadeTexelData} texel_data
|
|
170
|
+
* @returns {ShadeImage}
|
|
171
|
+
*/
|
|
172
|
+
static fromTexelData(texel_data) {
|
|
173
|
+
assert.defined(texel_data, 'texel_data');
|
|
174
|
+
assert.equal(texel_data.isShadeTexelData, true, 'texel_data.isShadeTexelData !== true');
|
|
175
|
+
|
|
176
|
+
const r = new ShadeImage();
|
|
177
|
+
|
|
178
|
+
r.#source = texel_data;
|
|
179
|
+
|
|
180
|
+
r.#size[0] = texel_data.width;
|
|
181
|
+
r.#size[1] = texel_data.height;
|
|
182
|
+
r.#size[2] = texel_data.depth;
|
|
183
|
+
|
|
184
|
+
return r;
|
|
185
|
+
}
|
|
186
|
+
|
|
113
187
|
hash() {
|
|
114
188
|
return this.#id;
|
|
115
189
|
}
|