@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,496 @@
|
|
|
1
|
+
import { etc1s_block_colors } from "../etc1s/etc1s_block_colors.js";
|
|
2
|
+
import { build_range_plan } from "./build_range_plan.js";
|
|
3
|
+
import { fit_endpoints, SELECTOR_RANGES } from "./fit_endpoints.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Bytes one BC7 block occupies.
|
|
7
|
+
*
|
|
8
|
+
* @readonly
|
|
9
|
+
* @type {number}
|
|
10
|
+
*/
|
|
11
|
+
const BC7_BLOCK_BYTES = 16;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* BC7's interpolation weights for four-bit indices, out of 64.
|
|
15
|
+
*
|
|
16
|
+
* @readonly
|
|
17
|
+
* @type {Int32Array}
|
|
18
|
+
*/
|
|
19
|
+
const WEIGHT4 = new Int32Array([0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64]);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* BC7's interpolation weights for two-bit indices, out of 64.
|
|
23
|
+
*
|
|
24
|
+
* @readonly
|
|
25
|
+
* @type {Int32Array}
|
|
26
|
+
*/
|
|
27
|
+
const WEIGHT2 = new Int32Array([0, 21, 43, 64]);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {number} a endpoint, eight bits
|
|
31
|
+
* @param {number} b endpoint, eight bits
|
|
32
|
+
* @param {number} weight out of 64
|
|
33
|
+
* @returns {number} the interpolated channel, as BC7 defines it
|
|
34
|
+
*/
|
|
35
|
+
function interpolate(a, b, weight) {
|
|
36
|
+
return (a * (64 - weight) + b * weight + 32) >> 6;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The eight-bit value a seven-bit endpoint decodes to, by BC7's bit replication.
|
|
41
|
+
*
|
|
42
|
+
* @param {number} value seven bits
|
|
43
|
+
* @returns {number}
|
|
44
|
+
*/
|
|
45
|
+
function replicate7(value) {
|
|
46
|
+
return ((value << 1) | (value >> 6)) & 255;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A little-endian bit accumulator over one block's sixteen bytes.
|
|
51
|
+
*
|
|
52
|
+
* BC7 fields are specified least significant bit first from byte zero, so writing them in the order
|
|
53
|
+
* the specification lists them is exactly writing the block.
|
|
54
|
+
*/
|
|
55
|
+
class Bc7BlockWriter {
|
|
56
|
+
/**
|
|
57
|
+
* @type {Uint8Array}
|
|
58
|
+
*/
|
|
59
|
+
#out = null;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Bit position within {@link #out}, not within the block.
|
|
63
|
+
* @type {number}
|
|
64
|
+
*/
|
|
65
|
+
#bit = 0;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @param {Uint8Array} out
|
|
69
|
+
* @param {number} byte_offset of the block
|
|
70
|
+
* @returns {Bc7BlockWriter} this
|
|
71
|
+
*/
|
|
72
|
+
init(out, byte_offset) {
|
|
73
|
+
this.#out = out;
|
|
74
|
+
this.#bit = byte_offset * 8;
|
|
75
|
+
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {number} value
|
|
81
|
+
* @param {number} count bits, at most 8
|
|
82
|
+
*/
|
|
83
|
+
write(value, count) {
|
|
84
|
+
for (let i = 0; i < count; i++) {
|
|
85
|
+
if (((value >> i) & 1) !== 0) {
|
|
86
|
+
this.#out[(this.#bit + i) >> 3] |= 1 << ((this.#bit + i) & 7);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
this.#bit += count;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Transcode a decoded ETC1S slice to BC7.
|
|
96
|
+
*
|
|
97
|
+
* **Two modes, chosen by whether the payload carries alpha, because BC7 cannot do both at once.**
|
|
98
|
+
* Mode 6 gives one index per texel, shared by all four channels, with four bits of it; mode 5 gives
|
|
99
|
+
* colour and alpha their own indices but only two bits each. An opaque payload wants the finer
|
|
100
|
+
* index; an alpha payload needs the independent one, because an ETC1S file's alpha slice has its own
|
|
101
|
+
* selectors, unrelated to the colour slice's, and a shared index could not express both.
|
|
102
|
+
*
|
|
103
|
+
* **The work is per codebook pairing, not per block.** What a block decodes to depends only on which
|
|
104
|
+
* endpoint entry and which selector entry it names, so endpoints are fitted once per (endpoint
|
|
105
|
+
* entry, selector span) pairing — see {@link fit_endpoints} for why the span is part of the key —
|
|
106
|
+
* and every block naming that pairing just writes the result out. Colour and alpha are tabulated
|
|
107
|
+
* separately, which is what lets mode 5 pair any colour entry with any alpha entry without a table
|
|
108
|
+
* of their product.
|
|
109
|
+
*
|
|
110
|
+
* @param {Etc1sSlice} slice the colour slice
|
|
111
|
+
* @param {Etc1sSlice|undefined} alpha_slice the alpha slice, when the payload has one
|
|
112
|
+
* @param {Etc1sEndpointCodebook} endpoints
|
|
113
|
+
* @param {Etc1sSelectorCodebook} selectors
|
|
114
|
+
* @returns {Uint8Array} tightly packed BC7 blocks, in raster order
|
|
115
|
+
*
|
|
116
|
+
* @author Alex Goldring
|
|
117
|
+
* @copyright Company Named Limited (c) 2026
|
|
118
|
+
*/
|
|
119
|
+
export function etc1s_to_bc7(slice, alpha_slice, endpoints, selectors) {
|
|
120
|
+
return alpha_slice === undefined
|
|
121
|
+
? to_mode6(slice, endpoints, selectors)
|
|
122
|
+
: to_mode5(slice, alpha_slice, endpoints, selectors);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The opaque path: one four-bit index per texel, alpha pinned opaque.
|
|
127
|
+
*
|
|
128
|
+
* @param {Etc1sSlice} slice
|
|
129
|
+
* @param {Etc1sEndpointCodebook} endpoints
|
|
130
|
+
* @param {Etc1sSelectorCodebook} selectors
|
|
131
|
+
* @returns {Uint8Array}
|
|
132
|
+
*/
|
|
133
|
+
function to_mode6(slice, endpoints, selectors) {
|
|
134
|
+
const plan = build_range_plan(selectors);
|
|
135
|
+
|
|
136
|
+
const templates = build_color_templates(endpoints, plan, WEIGHT4, quantise_mode6);
|
|
137
|
+
|
|
138
|
+
const block_count = slice.blocks_x * slice.blocks_y;
|
|
139
|
+
|
|
140
|
+
const out = new Uint8Array(block_count * BC7_BLOCK_BYTES);
|
|
141
|
+
|
|
142
|
+
const writer = new Bc7BlockWriter();
|
|
143
|
+
|
|
144
|
+
const indices = new Uint8Array(16);
|
|
145
|
+
|
|
146
|
+
for (let block = 0; block < block_count; block++) {
|
|
147
|
+
const selector_entry = slice.selector_index[block];
|
|
148
|
+
const selector_base = selector_entry * 16;
|
|
149
|
+
|
|
150
|
+
const pairing = slice.endpoint_index[block] * plan.slot_count
|
|
151
|
+
+ plan.slot_of_entry[selector_entry];
|
|
152
|
+
|
|
153
|
+
const e = pairing * 3;
|
|
154
|
+
|
|
155
|
+
const flipped = fill_indices(
|
|
156
|
+
indices, templates.selector_to_index, pairing, selectors, selector_base, WEIGHT4.length
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
writer.init(out, block * BC7_BLOCK_BYTES);
|
|
160
|
+
|
|
161
|
+
// mode 6 is signalled by six zero bits then a one
|
|
162
|
+
writer.write(0x40, 7);
|
|
163
|
+
|
|
164
|
+
/*
|
|
165
|
+
The endpoints go out in whichever order {@link fill_indices} settled on. Swapping them and
|
|
166
|
+
inverting every index leaves the decoded block identical — BC7's weight tables are symmetric
|
|
167
|
+
about their midpoint — which is what makes the anchor rule satisfiable without re-fitting.
|
|
168
|
+
*/
|
|
169
|
+
const first = flipped ? templates.high : templates.low;
|
|
170
|
+
const second = flipped ? templates.low : templates.high;
|
|
171
|
+
|
|
172
|
+
writer.write(first[e], 7);
|
|
173
|
+
writer.write(second[e], 7);
|
|
174
|
+
writer.write(first[e + 1], 7);
|
|
175
|
+
writer.write(second[e + 1], 7);
|
|
176
|
+
writer.write(first[e + 2], 7);
|
|
177
|
+
writer.write(second[e + 2], 7);
|
|
178
|
+
|
|
179
|
+
/*
|
|
180
|
+
Alpha, opaque. Both endpoints are seven ones and both parity bits are one, so each decodes
|
|
181
|
+
to exactly 255 — which is why the parity is fixed rather than fitted: an endpoint's parity
|
|
182
|
+
bit is shared with its alpha channel, and an opaque texture that decoded to 254 would be a
|
|
183
|
+
texture with alpha nobody asked for. It costs each colour channel one step out of 255.
|
|
184
|
+
*/
|
|
185
|
+
writer.write(0x7F, 7);
|
|
186
|
+
writer.write(0x7F, 7);
|
|
187
|
+
|
|
188
|
+
writer.write(1, 1);
|
|
189
|
+
writer.write(1, 1);
|
|
190
|
+
|
|
191
|
+
for (let texel = 0; texel < 16; texel++) {
|
|
192
|
+
writer.write(indices[texel], texel === 0 ? 3 : 4);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return out;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* The alpha path: two-bit colour and alpha indices, each with their own endpoints.
|
|
201
|
+
*
|
|
202
|
+
* @param {Etc1sSlice} slice
|
|
203
|
+
* @param {Etc1sSlice} alpha_slice
|
|
204
|
+
* @param {Etc1sEndpointCodebook} endpoints
|
|
205
|
+
* @param {Etc1sSelectorCodebook} selectors
|
|
206
|
+
* @returns {Uint8Array}
|
|
207
|
+
*/
|
|
208
|
+
function to_mode5(slice, alpha_slice, endpoints, selectors) {
|
|
209
|
+
const plan = build_range_plan(selectors);
|
|
210
|
+
|
|
211
|
+
const color = build_color_templates(endpoints, plan, WEIGHT2, quantise_mode5);
|
|
212
|
+
const alpha = build_alpha_templates(endpoints, plan);
|
|
213
|
+
|
|
214
|
+
const block_count = slice.blocks_x * slice.blocks_y;
|
|
215
|
+
|
|
216
|
+
const out = new Uint8Array(block_count * BC7_BLOCK_BYTES);
|
|
217
|
+
|
|
218
|
+
const writer = new Bc7BlockWriter();
|
|
219
|
+
|
|
220
|
+
const color_indices = new Uint8Array(16);
|
|
221
|
+
const alpha_indices = new Uint8Array(16);
|
|
222
|
+
|
|
223
|
+
for (let block = 0; block < block_count; block++) {
|
|
224
|
+
const selector_entry = slice.selector_index[block];
|
|
225
|
+
const selector_base = selector_entry * 16;
|
|
226
|
+
|
|
227
|
+
const alpha_selector_entry = alpha_slice.selector_index[block];
|
|
228
|
+
const alpha_selector_base = alpha_selector_entry * 16;
|
|
229
|
+
|
|
230
|
+
const pairing = slice.endpoint_index[block] * plan.slot_count
|
|
231
|
+
+ plan.slot_of_entry[selector_entry];
|
|
232
|
+
|
|
233
|
+
const alpha_pairing = alpha_slice.endpoint_index[block] * plan.slot_count
|
|
234
|
+
+ plan.slot_of_entry[alpha_selector_entry];
|
|
235
|
+
|
|
236
|
+
const e = pairing * 3;
|
|
237
|
+
|
|
238
|
+
/*
|
|
239
|
+
Mode 5 keeps two index sets and each has its own anchor, so each is normalised on its own —
|
|
240
|
+
which is exactly why the colour and alpha endpoints had to stay independent.
|
|
241
|
+
*/
|
|
242
|
+
const color_flipped = fill_indices(
|
|
243
|
+
color_indices, color.selector_to_index, pairing, selectors, selector_base,
|
|
244
|
+
WEIGHT2.length
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
const alpha_flipped = fill_indices(
|
|
248
|
+
alpha_indices, alpha.selector_to_index, alpha_pairing, selectors, alpha_selector_base,
|
|
249
|
+
WEIGHT2.length
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
writer.init(out, block * BC7_BLOCK_BYTES);
|
|
253
|
+
|
|
254
|
+
// mode 5 is signalled by five zero bits then a one, followed by a two-bit channel rotation
|
|
255
|
+
writer.write(0x20, 6);
|
|
256
|
+
writer.write(0, 2);
|
|
257
|
+
|
|
258
|
+
const first = color_flipped ? color.high : color.low;
|
|
259
|
+
const second = color_flipped ? color.low : color.high;
|
|
260
|
+
|
|
261
|
+
writer.write(first[e], 7);
|
|
262
|
+
writer.write(second[e], 7);
|
|
263
|
+
writer.write(first[e + 1], 7);
|
|
264
|
+
writer.write(second[e + 1], 7);
|
|
265
|
+
writer.write(first[e + 2], 7);
|
|
266
|
+
writer.write(second[e + 2], 7);
|
|
267
|
+
|
|
268
|
+
writer.write(alpha_flipped ? alpha.high[alpha_pairing] : alpha.low[alpha_pairing], 8);
|
|
269
|
+
writer.write(alpha_flipped ? alpha.low[alpha_pairing] : alpha.high[alpha_pairing], 8);
|
|
270
|
+
|
|
271
|
+
for (let texel = 0; texel < 16; texel++) {
|
|
272
|
+
writer.write(color_indices[texel], texel === 0 ? 1 : 2);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
for (let texel = 0; texel < 16; texel++) {
|
|
276
|
+
writer.write(alpha_indices[texel], texel === 0 ? 1 : 2);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return out;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Quantise a fitted eight-bit channel the way mode 6 stores it, with the parity bit fixed at one.
|
|
285
|
+
*
|
|
286
|
+
* @param {number} value
|
|
287
|
+
* @returns {{stored: number, decoded: number}}
|
|
288
|
+
*/
|
|
289
|
+
function quantise_mode6(value) {
|
|
290
|
+
const decoded = value | 1;
|
|
291
|
+
|
|
292
|
+
return { stored: decoded >> 1, decoded };
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Quantise a fitted eight-bit channel the way mode 5 stores a colour endpoint: seven bits, decoding
|
|
297
|
+
* by replication rather than by an appended parity bit.
|
|
298
|
+
*
|
|
299
|
+
* @param {number} value
|
|
300
|
+
* @returns {{stored: number, decoded: number}}
|
|
301
|
+
*/
|
|
302
|
+
function quantise_mode5(value) {
|
|
303
|
+
const stored = Math.min(127, (value * 127 + 127) / 255 | 0);
|
|
304
|
+
|
|
305
|
+
return { stored, decoded: replicate7(stored) };
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Fitted, quantised endpoints and a selector mapping for every (endpoint entry, selector span)
|
|
310
|
+
* pairing.
|
|
311
|
+
*
|
|
312
|
+
* @param {Etc1sEndpointCodebook} endpoints
|
|
313
|
+
* @param {{slot_count: number, range_of_slot: Uint8Array}} plan
|
|
314
|
+
* @param {Int32Array} weights
|
|
315
|
+
* @param {function(number): {stored: number, decoded: number}} quantise
|
|
316
|
+
* @returns {{low: Uint8Array, high: Uint8Array, selector_to_index: Uint8Array}}
|
|
317
|
+
*/
|
|
318
|
+
function build_color_templates(endpoints, plan, weights, quantise) {
|
|
319
|
+
const pairings = endpoints.count * plan.slot_count;
|
|
320
|
+
|
|
321
|
+
const low = new Uint8Array(pairings * 3);
|
|
322
|
+
const high = new Uint8Array(pairings * 3);
|
|
323
|
+
const selector_to_index = new Uint8Array(pairings * 4);
|
|
324
|
+
|
|
325
|
+
const colors = new Uint8Array(12);
|
|
326
|
+
const fitted_low = new Uint8Array(3);
|
|
327
|
+
const fitted_high = new Uint8Array(3);
|
|
328
|
+
const decoded_low = new Uint8Array(3);
|
|
329
|
+
const decoded_high = new Uint8Array(3);
|
|
330
|
+
|
|
331
|
+
for (let entry = 0; entry < endpoints.count; entry++) {
|
|
332
|
+
etc1s_block_colors(colors, 0, endpoints.color5, endpoints.intensity, entry);
|
|
333
|
+
|
|
334
|
+
for (let slot = 0; slot < plan.slot_count; slot++) {
|
|
335
|
+
const [min, max] = SELECTOR_RANGES[plan.range_of_slot[slot]];
|
|
336
|
+
|
|
337
|
+
for (let c = 0; c < 3; c++) {
|
|
338
|
+
fitted_low[c] = colors[min * 3 + c];
|
|
339
|
+
fitted_high[c] = colors[max * 3 + c];
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
fit_endpoints(fitted_low, fitted_high, colors, weights, min, max);
|
|
343
|
+
|
|
344
|
+
const pairing = entry * plan.slot_count + slot;
|
|
345
|
+
const e = pairing * 3;
|
|
346
|
+
|
|
347
|
+
for (let c = 0; c < 3; c++) {
|
|
348
|
+
const a = quantise(fitted_low[c]);
|
|
349
|
+
const b = quantise(fitted_high[c]);
|
|
350
|
+
|
|
351
|
+
low[e + c] = a.stored;
|
|
352
|
+
high[e + c] = b.stored;
|
|
353
|
+
|
|
354
|
+
decoded_low[c] = a.decoded;
|
|
355
|
+
decoded_high[c] = b.decoded;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/*
|
|
359
|
+
Assigned against the endpoints as they will *decode*, not as they were fitted.
|
|
360
|
+
Quantisation moves them, and an index chosen against the unquantised pair would be a
|
|
361
|
+
step off wherever that move mattered.
|
|
362
|
+
*/
|
|
363
|
+
for (let selector = 0; selector < 4; selector++) {
|
|
364
|
+
selector_to_index[pairing * 4 + selector] = closest_weight(
|
|
365
|
+
decoded_low, decoded_high, weights, colors, selector * 3
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return { low, high, selector_to_index };
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* The same, read as alpha.
|
|
376
|
+
*
|
|
377
|
+
* The alpha slice is an ordinary ETC1S image whose green channel carries the alpha, which is what
|
|
378
|
+
* the specification says of it — so the same codebook is read and one channel of it is kept. Mode 5
|
|
379
|
+
* gives alpha a full eight bits, so no quantisation happens and the endpoints of a two-value span
|
|
380
|
+
* are exact.
|
|
381
|
+
*
|
|
382
|
+
* @param {Etc1sEndpointCodebook} endpoints
|
|
383
|
+
* @param {{slot_count: number, range_of_slot: Uint8Array}} plan
|
|
384
|
+
* @returns {{low: Uint8Array, high: Uint8Array, selector_to_index: Uint8Array}}
|
|
385
|
+
*/
|
|
386
|
+
function build_alpha_templates(endpoints, plan) {
|
|
387
|
+
const pairings = endpoints.count * plan.slot_count;
|
|
388
|
+
|
|
389
|
+
const low = new Uint8Array(pairings);
|
|
390
|
+
const high = new Uint8Array(pairings);
|
|
391
|
+
const selector_to_index = new Uint8Array(pairings * 4);
|
|
392
|
+
|
|
393
|
+
const colors = new Uint8Array(12);
|
|
394
|
+
|
|
395
|
+
for (let entry = 0; entry < endpoints.count; entry++) {
|
|
396
|
+
etc1s_block_colors(colors, 0, endpoints.color5, endpoints.intensity, entry);
|
|
397
|
+
|
|
398
|
+
for (let slot = 0; slot < plan.slot_count; slot++) {
|
|
399
|
+
const [min, max] = SELECTOR_RANGES[plan.range_of_slot[slot]];
|
|
400
|
+
|
|
401
|
+
const pairing = entry * plan.slot_count + slot;
|
|
402
|
+
|
|
403
|
+
const a = colors[min * 3 + 1];
|
|
404
|
+
const b = colors[max * 3 + 1];
|
|
405
|
+
|
|
406
|
+
low[pairing] = a;
|
|
407
|
+
high[pairing] = b;
|
|
408
|
+
|
|
409
|
+
for (let selector = 0; selector < 4; selector++) {
|
|
410
|
+
const target = colors[selector * 3 + 1];
|
|
411
|
+
|
|
412
|
+
let best = 0;
|
|
413
|
+
let best_error = Infinity;
|
|
414
|
+
|
|
415
|
+
for (let i = 0; i < WEIGHT2.length; i++) {
|
|
416
|
+
const error = Math.abs(interpolate(a, b, WEIGHT2[i]) - target);
|
|
417
|
+
|
|
418
|
+
if (error < best_error) {
|
|
419
|
+
best_error = error;
|
|
420
|
+
best = i;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
selector_to_index[pairing * 4 + selector] = best;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
return { low, high, selector_to_index };
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Fill one block's indices, flipping them if the first texel's would not fit the anchor.
|
|
434
|
+
*
|
|
435
|
+
* **BC7 stores the first texel's index one bit short**, because a block is required to be written so
|
|
436
|
+
* that index's most significant bit is zero. Nothing about an ETC1S block guarantees that — the
|
|
437
|
+
* first texel is whatever it is — so a block whose first index is in the upper half is rewritten
|
|
438
|
+
* against the endpoints in the other order, which inverts every index and lands the first one in the
|
|
439
|
+
* lower half. The decoded result is unchanged, since BC7's weight tables are symmetric about their
|
|
440
|
+
* midpoint.
|
|
441
|
+
*
|
|
442
|
+
* @param {Uint8Array} out sixteen indices
|
|
443
|
+
* @param {Uint8Array} selector_to_index the pairing's mapping
|
|
444
|
+
* @param {number} pairing
|
|
445
|
+
* @param {Etc1sSelectorCodebook} selectors
|
|
446
|
+
* @param {number} selector_base into `selectors.selectors`
|
|
447
|
+
* @param {number} index_count how many index values the mode has
|
|
448
|
+
* @returns {boolean} whether the endpoints must be written in the other order
|
|
449
|
+
*/
|
|
450
|
+
function fill_indices(out, selector_to_index, pairing, selectors, selector_base, index_count) {
|
|
451
|
+
const map = pairing * 4;
|
|
452
|
+
|
|
453
|
+
const first = selector_to_index[map + selectors.selectors[selector_base]];
|
|
454
|
+
|
|
455
|
+
const flipped = first >= index_count / 2;
|
|
456
|
+
|
|
457
|
+
for (let texel = 0; texel < 16; texel++) {
|
|
458
|
+
const index = selector_to_index[map + selectors.selectors[selector_base + texel]];
|
|
459
|
+
|
|
460
|
+
out[texel] = flipped ? index_count - 1 - index : index;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return flipped;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Which interpolation weight best reproduces a target colour between two endpoints.
|
|
468
|
+
*
|
|
469
|
+
* @param {Uint8Array} a three channels, as they decode
|
|
470
|
+
* @param {Uint8Array} b three channels, as they decode
|
|
471
|
+
* @param {Int32Array} weights
|
|
472
|
+
* @param {Uint8Array} target
|
|
473
|
+
* @param {number} target_offset
|
|
474
|
+
* @returns {number} an index into `weights`
|
|
475
|
+
*/
|
|
476
|
+
function closest_weight(a, b, weights, target, target_offset) {
|
|
477
|
+
let best = 0;
|
|
478
|
+
let best_error = Infinity;
|
|
479
|
+
|
|
480
|
+
for (let i = 0; i < weights.length; i++) {
|
|
481
|
+
let error = 0;
|
|
482
|
+
|
|
483
|
+
for (let c = 0; c < 3; c++) {
|
|
484
|
+
const delta = interpolate(a[c], b[c], weights[i]) - target[target_offset + c];
|
|
485
|
+
|
|
486
|
+
error += delta * delta;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if (error < best_error) {
|
|
490
|
+
best_error = error;
|
|
491
|
+
best = i;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return best;
|
|
496
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which entry of {@link SELECTOR_RANGES} a `[min, max]` span is.
|
|
3
|
+
*
|
|
4
|
+
* @param {number} min
|
|
5
|
+
* @param {number} max
|
|
6
|
+
* @returns {number}
|
|
7
|
+
*/
|
|
8
|
+
export function selector_range_index(min: number, max: number): number;
|
|
9
|
+
/**
|
|
10
|
+
* Fit a pair of endpoints to the colours a block actually uses, by least squares.
|
|
11
|
+
*
|
|
12
|
+
* **Why the obvious choice is not good enough.** An ETC1S block's four colours are its base colour
|
|
13
|
+
* plus a modifier applied equally to every channel, so before clamping they lie on a line and the
|
|
14
|
+
* darkest and brightest of them span it exactly. Clamping breaks that. A base colour near white with
|
|
15
|
+
* a large modifier gives, say, red `{67, 203, 255, 255}` beside green `{0, 0, 57, 193}` — still
|
|
16
|
+
* ordered, but no longer collinear, because red saturated and green did not. Taking the outer two as
|
|
17
|
+
* endpoints then leaves the middle two nowhere near the line between them, and no interpolation
|
|
18
|
+
* weight can recover them.
|
|
19
|
+
*
|
|
20
|
+
* So the endpoints are fitted rather than read off: each colour is assigned the weight that suits it
|
|
21
|
+
* best, the endpoints are re-solved to minimise squared error against all of them at once, and the
|
|
22
|
+
* two steps alternate.
|
|
23
|
+
*
|
|
24
|
+
* **And the fit is over `[min_selector, max_selector]` only.** Which colours a block uses is a
|
|
25
|
+
* property of its *selector* codebook entry, and most entries do not use all four — a block spanning
|
|
26
|
+
* only the darkest two is a line those two define exactly, and fitting it against colours it never
|
|
27
|
+
* samples throws that away for nothing. Conditioning on the span is what closes most of the distance
|
|
28
|
+
* to the reference transcoder on saturated content.
|
|
29
|
+
*
|
|
30
|
+
* @param {Uint8Array} low three channels, seeded with a guess and overwritten with the fit
|
|
31
|
+
* @param {Uint8Array} high three channels, likewise
|
|
32
|
+
* @param {Uint8Array} colors twelve bytes, the block's four `[r, g, b]` colours
|
|
33
|
+
* @param {Int32Array} weights the destination format's interpolation weights, out of 64
|
|
34
|
+
* @param {number} min_selector lowest selector value any block using this pairing has
|
|
35
|
+
* @param {number} max_selector highest
|
|
36
|
+
*
|
|
37
|
+
* @author Alex Goldring
|
|
38
|
+
* @copyright Company Named Limited (c) 2026
|
|
39
|
+
*/
|
|
40
|
+
export function fit_endpoints(low: Uint8Array, high: Uint8Array, colors: Uint8Array, weights: Int32Array, min_selector: number, max_selector: number): void;
|
|
41
|
+
/**
|
|
42
|
+
* The `[min, max]` selector span of every entry of a selector codebook.
|
|
43
|
+
*
|
|
44
|
+
* @param {Etc1sSelectorCodebook} selectors
|
|
45
|
+
* @returns {Uint8Array} one index into {@link SELECTOR_RANGES} per entry
|
|
46
|
+
*/
|
|
47
|
+
export function selector_codebook_ranges(selectors: Etc1sSelectorCodebook): Uint8Array;
|
|
48
|
+
/**
|
|
49
|
+
* Every `[min, max]` span of selector values a block can use, as pairs.
|
|
50
|
+
*
|
|
51
|
+
* Ten of them, because a span is an ordered pair drawn from four values. A block that only uses the
|
|
52
|
+
* darkest two colours is fitted against those two alone, which is the whole reason this exists — see
|
|
53
|
+
* {@link fit_endpoints}.
|
|
54
|
+
*
|
|
55
|
+
* @readonly
|
|
56
|
+
* @type {number[][]}
|
|
57
|
+
*/
|
|
58
|
+
export const SELECTOR_RANGES: number[][];
|
|
59
|
+
//# sourceMappingURL=fit_endpoints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fit_endpoints.d.ts","sourceRoot":"","sources":["../../../../src/basis/transcode/fit_endpoints.js"],"names":[],"mappings":"AA2BA;;;;;;GAMG;AACH,0CAJW,MAAM,OACN,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,mCAVW,UAAU,QACV,UAAU,UACV,UAAU,WACV,UAAU,gBACV,MAAM,gBACN,MAAM,QA+EhB;AA+CD;;;;;GAKG;AACH,4EAFa,UAAU,CAyBtB;AAvND;;;;;;;;;GASG;AACH,8BAFU,MAAM,EAAE,EAAE,CAOlB"}
|