@threenative/assets 0.3.5 → 0.3.7
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/dist/apply-worker.js +9637 -8613
- package/dist/blender-gpl/recipes/export_world.py +18 -1
- package/dist/index.d.ts +143 -100
- package/dist/index.js +11338 -9687
- package/package.json +4 -3
|
@@ -388,6 +388,8 @@ def skipped_collections(layer, under_hidden=False):
|
|
|
388
388
|
|
|
389
389
|
def terrain_layer_texture(table_dir, textures, layer_id, kind):
|
|
390
390
|
"""The source file of one texture set's map, searched in the table's `textures.search` dirs."""
|
|
391
|
+
if kind not in textures:
|
|
392
|
+
fail("terrain layers: the table names no '%s' texture for a layer that asks for one" % kind)
|
|
391
393
|
name = textures[kind].replace("{id}", layer_id)
|
|
392
394
|
for relative in textures.get("search", ["."]):
|
|
393
395
|
base = os.path.normpath(os.path.join(table_dir, relative))
|
|
@@ -422,7 +424,9 @@ def export_terrain_layers(out, table_path, root=None):
|
|
|
422
424
|
The table (the game's; its DCC shader can read the same file) names its masks, texture sets and
|
|
423
425
|
blend values. This writes `terrain/layers.json` (the table plus the splat layout),
|
|
424
426
|
`terrain/splat.rgba8` (masks packed into RGBA8 planes, raw so no cook converts them) and
|
|
425
|
-
`terrain/tex/<id>_diff.jpg`
|
|
427
|
+
`terrain/tex/<id>_diff.jpg`, `<id>_nrm.jpg` and `<id>_orm.jpg`, and returns the
|
|
428
|
+
`terrain.layers` paths. A layer's `normal` and `orm` flags say which maps it ships, and its
|
|
429
|
+
`roughness`/`metalness` say how it answers light when it ships no ORM map.
|
|
426
430
|
Relative paths in the table resolve against `root` when given, else the table's folder.
|
|
427
431
|
"""
|
|
428
432
|
import numpy as np
|
|
@@ -476,6 +480,19 @@ def export_terrain_layers(out, table_path, root=None):
|
|
|
476
480
|
terrain_layer_texture(table_dir, textures, layer["id"], "nrm"),
|
|
477
481
|
os.path.join(tex, "%s_nrm.jpg" % layer["id"]),
|
|
478
482
|
)
|
|
483
|
+
if layer.get("orm"):
|
|
484
|
+
# A material with a roughness input of its own ships that input as occlusion,
|
|
485
|
+
# roughness and metalness; the table's numbers stand in for one without it.
|
|
486
|
+
shutil.copyfile(
|
|
487
|
+
terrain_layer_texture(table_dir, textures, layer["id"], "orm"),
|
|
488
|
+
os.path.join(tex, "%s_orm.jpg" % layer["id"]),
|
|
489
|
+
)
|
|
490
|
+
if layer.get("height"):
|
|
491
|
+
# The layer's own height, which the game's `layerWeight` reads; fails closed like orm.
|
|
492
|
+
shutil.copyfile(
|
|
493
|
+
terrain_layer_texture(table_dir, textures, layer["id"], "h"),
|
|
494
|
+
os.path.join(tex, "%s_h.jpg" % layer["id"]),
|
|
495
|
+
)
|
|
479
496
|
|
|
480
497
|
shipped = {key: table[key] for key in ("base", "breakup", "macro", "layers")}
|
|
481
498
|
shipped["splat"] = {"masks": placed, "planes": len(planes), "size": size}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,123 @@
|
|
|
1
1
|
import { Document, Material } from '@gltf-transform/core';
|
|
2
2
|
|
|
3
|
+
interface IImageQualityFloor {
|
|
4
|
+
readonly ssim: number;
|
|
5
|
+
readonly meanDeltaE00: number;
|
|
6
|
+
}
|
|
7
|
+
interface IImageQuality {
|
|
8
|
+
readonly version: string;
|
|
9
|
+
readonly width: number;
|
|
10
|
+
readonly height: number;
|
|
11
|
+
readonly ssim: number;
|
|
12
|
+
readonly meanDeltaE00: number | null;
|
|
13
|
+
readonly slots: readonly string[];
|
|
14
|
+
readonly floor: IImageQualityFloor;
|
|
15
|
+
readonly status: "pass" | "below-floor" | "unvalidated-slots";
|
|
16
|
+
readonly alpha: {
|
|
17
|
+
readonly ssim: number;
|
|
18
|
+
readonly meanAbsoluteError: number;
|
|
19
|
+
readonly coverage: readonly {
|
|
20
|
+
readonly threshold: number;
|
|
21
|
+
readonly source: number;
|
|
22
|
+
readonly decoded: number;
|
|
23
|
+
readonly changedPixels: number;
|
|
24
|
+
}[];
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
interface ITextureQuality extends IImageQuality {
|
|
28
|
+
readonly rung?: string;
|
|
29
|
+
readonly compressionSkipped?: "block-size" | "not-smaller" | "below-floor";
|
|
30
|
+
readonly sourceWidth: number;
|
|
31
|
+
readonly sourceHeight: number;
|
|
32
|
+
readonly codec: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Compresses the images embedded *inside* a `.glb` — the half of a model the geometry passes
|
|
37
|
+
* never touched. A prop carrying three 2048x2048 JPEGs is a small file and 67 MB of VRAM once
|
|
38
|
+
* the driver decodes it; meshopt shrinks the other, cheaper half. This stage transcodes each
|
|
39
|
+
* embedded image to KTX2/Basis and declares `KHR_texture_basisu`, so the GPU stores blocks
|
|
40
|
+
* instead of RGBA, and caps the resolution so a 4K texture an image model produced cannot
|
|
41
|
+
* silently eat a phone's whole budget.
|
|
42
|
+
*
|
|
43
|
+
* Slot constraints feed one measured ladder: normal/data slots retain UASTC/none, while
|
|
44
|
+
* colour escalates from ETC1S through RDO and plain UASTC. Alpha coverage is checked separately;
|
|
45
|
+
* a forced codec must still meet the floor. Colour space comes from the slot too — `getTextureColorSpace`
|
|
46
|
+
* knows base colour and emissive are sRGB and that metallic-roughness and normals are data —
|
|
47
|
+
* so a linear map is never encoded through a perceptual metric.
|
|
48
|
+
*
|
|
49
|
+
* The encoder is the same in-process Basis WASM the standalone texture pass uses, so no new
|
|
50
|
+
* dependency and nothing extra to install. Everything fails closed: an image no decoder reads,
|
|
51
|
+
* an image whose dimensions are not a whole number of 4x4 blocks, and a texture whose binding
|
|
52
|
+
* did not survive the round trip all throw naming the model and the image.
|
|
53
|
+
*/
|
|
54
|
+
interface IModelTextureOverride {
|
|
55
|
+
readonly codec: TextureCodec;
|
|
56
|
+
/** glTF slot the override applies to, e.g. `normalTexture` or `baseColorTexture`. */
|
|
57
|
+
readonly slot: string;
|
|
58
|
+
}
|
|
59
|
+
type TextureMaxSize = number | Readonly<Record<string, number>>;
|
|
60
|
+
interface IModelTexturesOptions {
|
|
61
|
+
/** Internal target-selected raw ASTC output. */
|
|
62
|
+
readonly astc?: boolean;
|
|
63
|
+
readonly floor?: Partial<IImageQualityFloor>;
|
|
64
|
+
/** Internal reporting switch; selection still measures and enforces the floor. */
|
|
65
|
+
readonly measureQuality?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Resolved by the compiler from the target's runtime capabilities, never by a project: the
|
|
68
|
+
* target has no KTX2 decoder, so an over-cap embedded image is box-resampled and re-emitted as
|
|
69
|
+
* a PNG instead of being encoded. Everything else — authored-byte retention under the cap,
|
|
70
|
+
* per-image deduplication, colour space — is unchanged.
|
|
71
|
+
*/
|
|
72
|
+
readonly decoderFree?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Longest edge an embedded image may keep, default 2048. Larger images are box-resampled
|
|
75
|
+
* down preserving aspect ratio; smaller ones are never upscaled.
|
|
76
|
+
*/
|
|
77
|
+
readonly maxSize?: TextureMaxSize;
|
|
78
|
+
readonly overrides?: readonly IModelTextureOverride[];
|
|
79
|
+
/** ETC1S encoder quality 1–255, default 150. Ignored for UASTC. */
|
|
80
|
+
readonly quality?: number;
|
|
81
|
+
}
|
|
82
|
+
/** What the stage did, recorded in the manifest and printed by the size report. */
|
|
83
|
+
interface IEmbeddedTextureSummary {
|
|
84
|
+
readonly quality: Readonly<Record<string, ITextureQuality>>;
|
|
85
|
+
readonly bytesAfter: number;
|
|
86
|
+
readonly bytesBefore: number;
|
|
87
|
+
readonly count: number;
|
|
88
|
+
/** Chosen codec per embedded image, keyed by texture name. */
|
|
89
|
+
readonly formats: Readonly<Record<string, string>>;
|
|
90
|
+
readonly gpuBytesAfter: number;
|
|
91
|
+
readonly gpuBytesBefore: number;
|
|
92
|
+
/** How many images the resolution cap actually downsampled. */
|
|
93
|
+
readonly resized: number;
|
|
94
|
+
/** Images retained at their authored bytes, by name, with the reason each one was not cooked. */
|
|
95
|
+
readonly skippedCompression: Readonly<Record<string, TextureSkipReason>>;
|
|
96
|
+
}
|
|
97
|
+
/** One embedded image as the verification compares it, source against re-read output. */
|
|
98
|
+
interface IModelTextureBinding {
|
|
99
|
+
readonly height: number;
|
|
100
|
+
readonly key: string;
|
|
101
|
+
/** KTX2 mip levels; 1 for a still-uncompressed source image. */
|
|
102
|
+
readonly levels: number;
|
|
103
|
+
readonly mimeType: string;
|
|
104
|
+
readonly slots: readonly string[];
|
|
105
|
+
readonly texCoords: readonly number[];
|
|
106
|
+
readonly width: number;
|
|
107
|
+
}
|
|
108
|
+
interface IModelTextureBindings {
|
|
109
|
+
/** `material -> slot=textureIndex@uvN` for the five core glTF slots, in document order. */
|
|
110
|
+
readonly materials: readonly string[];
|
|
111
|
+
readonly textures: readonly IModelTextureBinding[];
|
|
112
|
+
}
|
|
113
|
+
|
|
3
114
|
/**
|
|
4
115
|
* Encodes compiled textures to KTX2/Basis so the GPU stores them compressed instead of as
|
|
5
116
|
* decoded RGBA (a 2048x2048 PNG is 16 MB in VRAM; BC7/ASTC hold it in a quarter of that).
|
|
6
117
|
*
|
|
7
118
|
* Codec choice is a declared property of the asset, never a guess: a config override wins,
|
|
8
|
-
* then the `*_normal.*` / `_nrm.*` filename convention
|
|
9
|
-
*
|
|
119
|
+
* then the `*_normal.*` / `_nrm.*` filename convention constrains the shared measured ladder.
|
|
120
|
+
* Colour escalates through ETC1S/RDO/UASTC/none; unknown alpha cutoffs require exact alpha. Mip chains are generated at
|
|
10
121
|
* encode time — always — because an uploaded compressed texture without mips looks worse
|
|
11
122
|
* than the PNG it replaced.
|
|
12
123
|
*
|
|
@@ -18,10 +129,10 @@ type TextureCodec = "etc1s" | "none" | "uastc";
|
|
|
18
129
|
/**
|
|
19
130
|
* Why a source shipped uncompressed although its pass ran. `not-smaller` means encoding would
|
|
20
131
|
* have grown the download; `block-size` means no block codec can address the source's
|
|
21
|
-
* dimensions.
|
|
132
|
+
* dimensions; `below-floor` means no compressed rung passed. A capped source retains its resized pixels as PNG; none is a silent decision — the manifest carries
|
|
22
133
|
* the reason and the report prints it.
|
|
23
134
|
*/
|
|
24
|
-
type TextureSkipReason = "block-size" | "not-smaller";
|
|
135
|
+
type TextureSkipReason = "block-size" | "not-smaller" | "below-floor";
|
|
25
136
|
interface ITextureOverride {
|
|
26
137
|
readonly codec: TextureCodec;
|
|
27
138
|
/** First matching override wins; matched against the logical path, e.g. "ui/x.png". */
|
|
@@ -30,8 +141,13 @@ interface ITextureOverride {
|
|
|
30
141
|
readonly quality?: number;
|
|
31
142
|
}
|
|
32
143
|
interface ITexturePassOptions {
|
|
144
|
+
/** Compiler-selected mobile output; the quality ladder measures final ASTC bytes. */
|
|
145
|
+
readonly astc?: boolean;
|
|
146
|
+
readonly floor?: Partial<IImageQualityFloor>;
|
|
147
|
+
/** Internal reporting control; selection still measures and enforces the floor. */
|
|
148
|
+
readonly measureQuality?: boolean;
|
|
33
149
|
/** Longest edge to retain; larger sources are downsampled without upscaling. */
|
|
34
|
-
readonly maxSize?:
|
|
150
|
+
readonly maxSize?: TextureMaxSize;
|
|
35
151
|
readonly overrides?: readonly ITextureOverride[];
|
|
36
152
|
/** ETC1S encoder quality 1–255, default 150. Ignored for UASTC. */
|
|
37
153
|
readonly quality?: number;
|
|
@@ -409,78 +525,6 @@ interface IModelVirtualOptions {
|
|
|
409
525
|
readonly simplifyRatio?: number;
|
|
410
526
|
}
|
|
411
527
|
|
|
412
|
-
/**
|
|
413
|
-
* Compresses the images embedded *inside* a `.glb` — the half of a model the geometry passes
|
|
414
|
-
* never touched. A prop carrying three 2048x2048 JPEGs is a small file and 67 MB of VRAM once
|
|
415
|
-
* the driver decodes it; meshopt shrinks the other, cheaper half. This stage transcodes each
|
|
416
|
-
* embedded image to KTX2/Basis and declares `KHR_texture_basisu`, so the GPU stores blocks
|
|
417
|
-
* instead of RGBA, and caps the resolution so a 4K texture an image model produced cannot
|
|
418
|
-
* silently eat a phone's whole budget.
|
|
419
|
-
*
|
|
420
|
-
* Codec choice follows the declared use of the image, never a guess: a config override on the
|
|
421
|
-
* glTF slot wins, then normal-map slots (UASTC survives normal data; ETC1S does not), then
|
|
422
|
-
* alpha in the decoded pixels. Colour space comes from the slot too — `getTextureColorSpace`
|
|
423
|
-
* knows base colour and emissive are sRGB and that metallic-roughness and normals are data —
|
|
424
|
-
* so a linear map is never encoded through a perceptual metric.
|
|
425
|
-
*
|
|
426
|
-
* The encoder is the same in-process Basis WASM the standalone texture pass uses, so no new
|
|
427
|
-
* dependency and nothing extra to install. Everything fails closed: an image no decoder reads,
|
|
428
|
-
* an image whose dimensions are not a whole number of 4x4 blocks, and a texture whose binding
|
|
429
|
-
* did not survive the round trip all throw naming the model and the image.
|
|
430
|
-
*/
|
|
431
|
-
interface IModelTextureOverride {
|
|
432
|
-
readonly codec: TextureCodec;
|
|
433
|
-
/** glTF slot the override applies to, e.g. `normalTexture` or `baseColorTexture`. */
|
|
434
|
-
readonly slot: string;
|
|
435
|
-
}
|
|
436
|
-
interface IModelTexturesOptions {
|
|
437
|
-
/**
|
|
438
|
-
* Resolved by the compiler from the target's runtime capabilities, never by a project: the
|
|
439
|
-
* target has no KTX2 decoder, so an over-cap embedded image is box-resampled and re-emitted as
|
|
440
|
-
* a PNG instead of being encoded. Everything else — authored-byte retention under the cap,
|
|
441
|
-
* per-image deduplication, colour space — is unchanged.
|
|
442
|
-
*/
|
|
443
|
-
readonly decoderFree?: boolean;
|
|
444
|
-
/**
|
|
445
|
-
* Longest edge an embedded image may keep, default 2048. Larger images are box-resampled
|
|
446
|
-
* down preserving aspect ratio; smaller ones are never upscaled.
|
|
447
|
-
*/
|
|
448
|
-
readonly maxSize?: number;
|
|
449
|
-
readonly overrides?: readonly IModelTextureOverride[];
|
|
450
|
-
/** ETC1S encoder quality 1–255, default 150. Ignored for UASTC. */
|
|
451
|
-
readonly quality?: number;
|
|
452
|
-
}
|
|
453
|
-
/** What the stage did, recorded in the manifest and printed by the size report. */
|
|
454
|
-
interface IEmbeddedTextureSummary {
|
|
455
|
-
readonly bytesAfter: number;
|
|
456
|
-
readonly bytesBefore: number;
|
|
457
|
-
readonly count: number;
|
|
458
|
-
/** Chosen codec per embedded image, keyed by texture name. */
|
|
459
|
-
readonly formats: Readonly<Record<string, string>>;
|
|
460
|
-
readonly gpuBytesAfter: number;
|
|
461
|
-
readonly gpuBytesBefore: number;
|
|
462
|
-
/** How many images the resolution cap actually downsampled. */
|
|
463
|
-
readonly resized: number;
|
|
464
|
-
/** Images retained at their authored bytes, by name, with the reason each one was not cooked. */
|
|
465
|
-
readonly skippedCompression: Readonly<Record<string, TextureSkipReason>>;
|
|
466
|
-
}
|
|
467
|
-
/** One embedded image as the verification compares it, source against re-read output. */
|
|
468
|
-
interface IModelTextureBinding {
|
|
469
|
-
readonly height: number;
|
|
470
|
-
readonly key: string;
|
|
471
|
-
/** KTX2 mip levels; 1 for a still-uncompressed source image. */
|
|
472
|
-
readonly levels: number;
|
|
473
|
-
readonly mimeType: string;
|
|
474
|
-
readonly slots: readonly string[];
|
|
475
|
-
readonly texCoords: readonly number[];
|
|
476
|
-
readonly width: number;
|
|
477
|
-
}
|
|
478
|
-
interface IModelTextureBindings {
|
|
479
|
-
/** `material -> slot=textureIndex@uvN` for the five core glTF slots, in document order. */
|
|
480
|
-
readonly materials: readonly string[];
|
|
481
|
-
readonly textures: readonly IModelTextureBinding[];
|
|
482
|
-
}
|
|
483
|
-
|
|
484
528
|
/**
|
|
485
529
|
* Images that models share, written once and referenced from every model that carries them.
|
|
486
530
|
*
|
|
@@ -495,6 +539,7 @@ interface IModelTextureBindings {
|
|
|
495
539
|
* bytes resolve to one URL and the browser cache, the bundle and the delete-test all see one file.
|
|
496
540
|
*/
|
|
497
541
|
interface ISharedImage {
|
|
542
|
+
readonly quality?: ITextureQuality;
|
|
498
543
|
readonly buffer: Buffer;
|
|
499
544
|
/** `uastc`, `etc1s` or `none`, spelled into the filename so a cache hit knows what it found. */
|
|
500
545
|
readonly codec: string;
|
|
@@ -624,6 +669,7 @@ declare function modelPass(options?: IModelPassOptions): IAssetPass;
|
|
|
624
669
|
* so tests can pin the exact lines a build prints.
|
|
625
670
|
*/
|
|
626
671
|
interface ITextureSizeRow {
|
|
672
|
+
readonly quality?: ITextureQuality;
|
|
627
673
|
readonly after: number;
|
|
628
674
|
readonly before: number;
|
|
629
675
|
/** Set when the bytes shipped as authored; printed so a flat row is never left unexplained. */
|
|
@@ -634,6 +680,7 @@ interface ITextureSizeRow {
|
|
|
634
680
|
declare function formatTextureSizes(rows: readonly ITextureSizeRow[]): readonly string[];
|
|
635
681
|
/** What the model pass did to the images inside one `.glb`. */
|
|
636
682
|
interface IEmbeddedTextureRow {
|
|
683
|
+
readonly quality?: Readonly<Record<string, ITextureQuality>>;
|
|
637
684
|
readonly skippedCompression?: Readonly<Record<string, TextureSkipReason>>;
|
|
638
685
|
readonly bytesAfter: number;
|
|
639
686
|
readonly bytesBefore: number;
|
|
@@ -648,6 +695,8 @@ interface IEmbeddedTextureRow {
|
|
|
648
695
|
interface IVirtualRow {
|
|
649
696
|
readonly bakeSeconds: number;
|
|
650
697
|
readonly clusters: number;
|
|
698
|
+
/** Primitives handed back to the discrete ladder because their DAG reduced nothing. */
|
|
699
|
+
readonly declined: number;
|
|
651
700
|
readonly levels: number;
|
|
652
701
|
readonly payloadBytes: number;
|
|
653
702
|
readonly primitives: number;
|
|
@@ -972,6 +1021,14 @@ interface IAssetSourceConfig {
|
|
|
972
1021
|
* default-on decision is a later phase (PRD-377 §8).
|
|
973
1022
|
*/
|
|
974
1023
|
readonly lod?: boolean | IModelLodOptions | "none";
|
|
1024
|
+
/**
|
|
1025
|
+
* Also writes the native cooked package (`<output>/native/assets.tnpk`, TNPK v1) beside the
|
|
1026
|
+
* existing outputs: one Buffer entry per cooked binary buffer and one Texture entry per cooked
|
|
1027
|
+
* PNG or JPEG (decoded to RGBA8). Mesh, material and scene entries are out of scope until their
|
|
1028
|
+
* native loaders land.
|
|
1029
|
+
* Absent means off, so a web-only project pays nothing.
|
|
1030
|
+
*/
|
|
1031
|
+
readonly nativePackage?: boolean;
|
|
975
1032
|
readonly output?: string;
|
|
976
1033
|
readonly source?: string;
|
|
977
1034
|
readonly targets?: IAssetTargets;
|
|
@@ -1021,7 +1078,8 @@ interface IAudioConfig {
|
|
|
1021
1078
|
readonly seamMaxRatio?: number;
|
|
1022
1079
|
}
|
|
1023
1080
|
interface ITexturesConfig {
|
|
1024
|
-
readonly
|
|
1081
|
+
readonly floor?: ITexturePassOptions["floor"];
|
|
1082
|
+
readonly maxSize?: TextureMaxSize;
|
|
1025
1083
|
readonly overrides?: readonly ITextureOverride[];
|
|
1026
1084
|
readonly quality?: number;
|
|
1027
1085
|
}
|
|
@@ -1046,31 +1104,16 @@ interface IAssetCompileOptions {
|
|
|
1046
1104
|
*/
|
|
1047
1105
|
readonly processingOrder?: "reversed" | "sorted";
|
|
1048
1106
|
/**
|
|
1049
|
-
* The
|
|
1050
|
-
*
|
|
1051
|
-
*
|
|
1052
|
-
*
|
|
1053
|
-
* a black screen, and `threenative build` refuses one with `TN_NATIVE_KTX2_UNSUPPORTED`. Web
|
|
1054
|
-
* and desktop decode both.
|
|
1055
|
-
*
|
|
1056
|
-
* Absent means web — a direct `compileAssets` call, or a project that compiles once and serves
|
|
1057
|
-
* the result. `threenative build` always names its `--target`, so the passes that a platform
|
|
1058
|
-
* cannot decode drop for that build and stay on for every other one. This is the whole reason
|
|
1059
|
-
* `assets.textures: "none"` used to be pinned in the scaffolded config: the author was asked to
|
|
1060
|
-
* choose one constant for four targets, and every game that wanted Android shipped its web
|
|
1061
|
-
* build uncompressed too. The build knows its target; it decides.
|
|
1107
|
+
* The conservative default decoder policy: web/desktop keep the existing loaders;
|
|
1108
|
+
* Android/iOS stay decoder-free until their packaged loaders are qualified. A V8 engine
|
|
1109
|
+
* alone does not establish a working Basis, Meshopt or Draco path. Absent means web.
|
|
1110
|
+
* Native builds provide runtimeDecoders from their selected artifact instead.
|
|
1062
1111
|
*/
|
|
1063
1112
|
readonly platform?: "android" | "desktop" | "ios" | "web";
|
|
1064
|
-
/**
|
|
1065
|
-
* What the runtime that will execute this bake can decode, when the caller has probed it.
|
|
1066
|
-
*
|
|
1067
|
-
* `platform` is a proxy: it answers "android and iOS have no WebAssembly" for the targets this
|
|
1068
|
-
* repository ships. A desktop host can also lack WebAssembly — the Linux arm64 lane builds
|
|
1069
|
-
* QuickJS over wgpu-native — and then the same meshopt/KTX2 passes it would keep produce an
|
|
1070
|
-
* asset nothing can decode. `threenative build` reads the engine from the runtime binary it will
|
|
1071
|
-
* package and passes the real capability here; absent, the platform-derived default stands.
|
|
1072
|
-
*/
|
|
1113
|
+
/** Which compressed outputs the selected runtime's bundle can decode, independently of WASM. */
|
|
1073
1114
|
readonly runtimeDecoders?: IAssetRuntimeDecoderCapabilities;
|
|
1115
|
+
/** Exact selected runtime/cohort identity; changing it invalidates cooked output. */
|
|
1116
|
+
readonly runtimeIdentity?: string;
|
|
1074
1117
|
readonly source?: string;
|
|
1075
1118
|
/** Overrides resolution of three's Basis transcoder for the copy into the output root. */
|
|
1076
1119
|
readonly transcoder?: IBasisTranscoder;
|