@driftengine/assets 4.1.2 → 4.1.4
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 +1 -1
- package/dist/drftLoader.js +27 -10
- package/dist/index.d.ts +2 -0
- package/dist/index.js +13 -0
- package/dist/kn5.js +20 -1
- package/package.json +4 -4
- package/src/drftLoader.ts +27 -10
- package/src/index.ts +27 -0
- package/src/kn5.ts +22 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Model readers for seven formats, and the streaming loader that uploads them.
|
|
4
4
|
|
|
5
|
-
**Cost: 12.
|
|
5
|
+
**Cost: 12.7 KB gzipped on top of core.** Measured by `scripts/size-gate.test.mjs`, which fails if it drifts more than
|
|
6
6
|
3% — the number is a fact about the build rather than a claim in a document.
|
|
7
7
|
|
|
8
8
|
Part of [DriftEngine](../../README.md). See [`docs/ARCHITECTURE.md`](../../docs/ARCHITECTURE.md)
|
package/dist/drftLoader.js
CHANGED
|
@@ -950,20 +950,37 @@ export function isRawCodec(codec) {
|
|
|
950
950
|
* the view would keep the whole file alive for as long as the image does.
|
|
951
951
|
*/
|
|
952
952
|
/**
|
|
953
|
-
* How every image a model carries is decoded: **
|
|
953
|
+
* How every image a model carries is decoded: **premultiplied, and no colour conversion.**
|
|
954
954
|
*
|
|
955
|
-
*
|
|
956
|
-
*
|
|
957
|
-
* emblem loses the colour its author padded past its edge
|
|
958
|
-
*
|
|
959
|
-
*
|
|
960
|
-
*
|
|
955
|
+
* **Straight alpha was tried in 4.0.0 and it is what this reverts.** The argument for it was that
|
|
956
|
+
* `createImageBitmap` premultiplies by default, so a texel with no alpha comes back with no colour
|
|
957
|
+
* and a cutout or an emblem loses the colour its author padded past its edge. That reasoning is
|
|
958
|
+
* sound about the pixels and wrong about the content: an imported material's albedo routinely
|
|
959
|
+
* carries arbitrary bytes under its fully transparent texels, and premultiplying was what kept
|
|
960
|
+
* them out of the frame.
|
|
961
961
|
*
|
|
962
|
-
* What it
|
|
963
|
-
*
|
|
962
|
+
* **What it cost, reported and then reproduced.** A car came through with its interior, grille,
|
|
963
|
+
* mirrors and lamps as hard black and white shards. Held frames of one scene in the showroom, on
|
|
964
|
+
* one machine, at one frame: a model with 41 images drew clean and two with 64 and 65 drew shards,
|
|
965
|
+
* on **both** backends, with the old container and the new one alike — the count only decides how
|
|
966
|
+
* likely a model is to carry a masked texture at all. Restoring this one option drew the car
|
|
967
|
+
* correctly again.
|
|
968
|
+
*
|
|
969
|
+
* **Why an opaque material sees it.** Nothing discards on an opaque draw, so the shader takes
|
|
970
|
+
* `texel.rgb` whatever the alpha beside it says. Premultiplied, the bytes under a mask arrive as
|
|
971
|
+
* black and disappear into a dark surface; straight, they arrive as whatever the exporter left
|
|
972
|
+
* there. A material that genuinely means to cut out says so with its own alpha reference, which is
|
|
973
|
+
* what `kn5.ts`'s `alphaReference` now reads correctly.
|
|
974
|
+
*
|
|
975
|
+
* **What would make this wrong:** content authored *for* straight alpha, whose colour under a mask
|
|
976
|
+
* is meaningful and wanted — a decal atlas relying on the padding. Nothing measured here is that,
|
|
977
|
+
* and the day one arrives it wants the option per material rather than per engine.
|
|
978
|
+
*
|
|
979
|
+
* `colorSpaceConversion` stays off: a normal or ORM map holds values that are not colours, and
|
|
980
|
+
* glTF says an image's own colour metadata is ignored.
|
|
964
981
|
*/
|
|
965
982
|
const AS_AUTHORED = {
|
|
966
|
-
premultiplyAlpha: '
|
|
983
|
+
premultiplyAlpha: 'premultiply',
|
|
967
984
|
colorSpaceConversion: 'none',
|
|
968
985
|
};
|
|
969
986
|
async function decodeImage(texture, longestSide) {
|
package/dist/index.d.ts
CHANGED
|
@@ -70,4 +70,6 @@ export type { ClusterOptions, ClusterSet } from './bake/cluster.ts';
|
|
|
70
70
|
export { buildClusterDag } from './bake/clusterLod.ts';
|
|
71
71
|
export type { ClusterDag, ClusterLevel } from './bake/clusterLod.ts';
|
|
72
72
|
export { bakeObjectSdf } from './bake/sdf.ts';
|
|
73
|
+
export { IMPOSTOR_GUTTER, IMPOSTOR_TILE, PROXY_BASE_CELLS, PROXY_MIN_CELLS, buildImpostor, buildProxy, frameOf, octahedralCoord, octahedralDirection, proxyResolution, rasteriseView, sampleImpostor, } from './bake/hlod.ts';
|
|
74
|
+
export type { Impostor, ProxyCell, ViewFrame } from './bake/hlod.ts';
|
|
73
75
|
export type { ObjectSdf } from './bake/sdf.ts';
|
package/dist/index.js
CHANGED
|
@@ -165,3 +165,16 @@ export { buildClusterDag } from './bake/clusterLod.js';
|
|
|
165
165
|
* carries, and a field a consumer cannot bake is a pipeline with no input.
|
|
166
166
|
*/
|
|
167
167
|
export { bakeObjectSdf } from './bake/sdf.js';
|
|
168
|
+
/*
|
|
169
|
+
* **The third time, and the one that got furthest before anybody noticed.** `bake/hlod.ts` builds
|
|
170
|
+
* the proxies and impostors `docs/CAPABILITIES.md` lists as shipping, it is tested, it is sized and
|
|
171
|
+
* it carries the licence — and until this line its only importer in the whole repository was its
|
|
172
|
+
* own test. A consumer following "the barrel is the contract" could read the row, believe the
|
|
173
|
+
* capability, and find no way to call it.
|
|
174
|
+
*
|
|
175
|
+
* The paragraph above says a demo boundary test caught the cluster case. Nothing caught this one,
|
|
176
|
+
* because no scene tried to bake an impostor — which is what the two paragraphs above are worth
|
|
177
|
+
* together: **a module reached only by its own test is not shipped, and no gate here asks.** Found
|
|
178
|
+
* by censusing what three consumers could adopt and what they could not.
|
|
179
|
+
*/
|
|
180
|
+
export { IMPOSTOR_GUTTER, IMPOSTOR_TILE, PROXY_BASE_CELLS, PROXY_MIN_CELLS, buildImpostor, buildProxy, frameOf, octahedralCoord, octahedralDirection, proxyResolution, rasteriseView, sampleImpostor, } from './bake/hlod.js';
|
package/dist/kn5.js
CHANGED
|
@@ -311,6 +311,25 @@ export function readKn5Nodes(header) {
|
|
|
311
311
|
* this stays only for the warning, which is the thing a name genuinely can answer: a shader
|
|
312
312
|
* nobody here has seen is still geometry somebody wants.
|
|
313
313
|
*/
|
|
314
|
+
/**
|
|
315
|
+
* What a tested material's alpha reference actually is, where it states zero or states none.
|
|
316
|
+
*
|
|
317
|
+
* **Zero means the shader's own threshold, not "discard nothing".** A material that says it is
|
|
318
|
+
* alpha tested has already said that something is meant to be discarded, so a reference of zero
|
|
319
|
+
* cannot be read literally without contradicting the flag beside it. Assetto Corsa's `*AT*` shaders
|
|
320
|
+
* carry a built-in reference and a material overrides it by stating one; stating zero is how a
|
|
321
|
+
* material says it is not overriding anything.
|
|
322
|
+
*
|
|
323
|
+
* **A half, because that is the convention those shaders were authored against**, and because the
|
|
324
|
+
* masks in question are two-valued: a grille's hole and a seat's stitching are cut out of a texture
|
|
325
|
+
* whose alpha is 0 or 255, so any threshold strictly inside the range separates them identically.
|
|
326
|
+
* What would make this wrong is a material whose mask is a soft gradient, which wants blending
|
|
327
|
+
* rather than a test and says so with `alphaBlendMode`.
|
|
328
|
+
*/
|
|
329
|
+
const DEFAULT_ALPHA_REFERENCE = 0.5;
|
|
330
|
+
function alphaReference(stated) {
|
|
331
|
+
return stated > 0 ? stated : DEFAULT_ALPHA_REFERENCE;
|
|
332
|
+
}
|
|
314
333
|
const KNOWN_SHADERS = new Set([
|
|
315
334
|
'ksPerPixelAlpha',
|
|
316
335
|
'ksWindscreen',
|
|
@@ -441,7 +460,7 @@ export function kn5ToMeshes(buffer) {
|
|
|
441
460
|
* rather than on evidence — stated plainly for the same reason the bone block is read past
|
|
442
461
|
* rather than interpreted. What the change fixes is not this line but the one above it.
|
|
443
462
|
*/
|
|
444
|
-
cutout: material.alphaTested ? property('ksAlphaRef', 0) : 0,
|
|
463
|
+
cutout: material.alphaTested ? alphaReference(property('ksAlphaRef', 0)) : 0,
|
|
445
464
|
albedo: bind(material, 'txDiffuse'),
|
|
446
465
|
normalMap: bind(material, 'txNormal'),
|
|
447
466
|
/*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@driftengine/assets",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.4",
|
|
4
4
|
"description": "Model readers and the streaming loader for the .drft container",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
],
|
|
28
28
|
"sideEffects": false,
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@driftengine/drft": "4.1.
|
|
31
|
-
"@driftengine/texture": "4.1.
|
|
30
|
+
"@driftengine/drft": "4.1.4",
|
|
31
|
+
"@driftengine/texture": "4.1.4"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@driftengine/core": "4.1.
|
|
34
|
+
"@driftengine/core": "4.1.4"
|
|
35
35
|
},
|
|
36
36
|
"author": "Drift Technologies",
|
|
37
37
|
"repository": {
|
package/src/drftLoader.ts
CHANGED
|
@@ -1162,20 +1162,37 @@ export function isRawCodec(codec: number): boolean {
|
|
|
1162
1162
|
* the view would keep the whole file alive for as long as the image does.
|
|
1163
1163
|
*/
|
|
1164
1164
|
/**
|
|
1165
|
-
* How every image a model carries is decoded: **
|
|
1165
|
+
* How every image a model carries is decoded: **premultiplied, and no colour conversion.**
|
|
1166
1166
|
*
|
|
1167
|
-
*
|
|
1168
|
-
*
|
|
1169
|
-
* emblem loses the colour its author padded past its edge
|
|
1170
|
-
*
|
|
1171
|
-
*
|
|
1172
|
-
*
|
|
1167
|
+
* **Straight alpha was tried in 4.0.0 and it is what this reverts.** The argument for it was that
|
|
1168
|
+
* `createImageBitmap` premultiplies by default, so a texel with no alpha comes back with no colour
|
|
1169
|
+
* and a cutout or an emblem loses the colour its author padded past its edge. That reasoning is
|
|
1170
|
+
* sound about the pixels and wrong about the content: an imported material's albedo routinely
|
|
1171
|
+
* carries arbitrary bytes under its fully transparent texels, and premultiplying was what kept
|
|
1172
|
+
* them out of the frame.
|
|
1173
1173
|
*
|
|
1174
|
-
* What it
|
|
1175
|
-
*
|
|
1174
|
+
* **What it cost, reported and then reproduced.** A car came through with its interior, grille,
|
|
1175
|
+
* mirrors and lamps as hard black and white shards. Held frames of one scene in the showroom, on
|
|
1176
|
+
* one machine, at one frame: a model with 41 images drew clean and two with 64 and 65 drew shards,
|
|
1177
|
+
* on **both** backends, with the old container and the new one alike — the count only decides how
|
|
1178
|
+
* likely a model is to carry a masked texture at all. Restoring this one option drew the car
|
|
1179
|
+
* correctly again.
|
|
1180
|
+
*
|
|
1181
|
+
* **Why an opaque material sees it.** Nothing discards on an opaque draw, so the shader takes
|
|
1182
|
+
* `texel.rgb` whatever the alpha beside it says. Premultiplied, the bytes under a mask arrive as
|
|
1183
|
+
* black and disappear into a dark surface; straight, they arrive as whatever the exporter left
|
|
1184
|
+
* there. A material that genuinely means to cut out says so with its own alpha reference, which is
|
|
1185
|
+
* what `kn5.ts`'s `alphaReference` now reads correctly.
|
|
1186
|
+
*
|
|
1187
|
+
* **What would make this wrong:** content authored *for* straight alpha, whose colour under a mask
|
|
1188
|
+
* is meaningful and wanted — a decal atlas relying on the padding. Nothing measured here is that,
|
|
1189
|
+
* and the day one arrives it wants the option per material rather than per engine.
|
|
1190
|
+
*
|
|
1191
|
+
* `colorSpaceConversion` stays off: a normal or ORM map holds values that are not colours, and
|
|
1192
|
+
* glTF says an image's own colour metadata is ignored.
|
|
1176
1193
|
*/
|
|
1177
1194
|
const AS_AUTHORED = {
|
|
1178
|
-
premultiplyAlpha: '
|
|
1195
|
+
premultiplyAlpha: 'premultiply',
|
|
1179
1196
|
colorSpaceConversion: 'none',
|
|
1180
1197
|
} as const satisfies ImageBitmapOptions;
|
|
1181
1198
|
|
package/src/index.ts
CHANGED
|
@@ -199,4 +199,31 @@ export type { ClusterDag, ClusterLevel } from './bake/clusterLod.ts';
|
|
|
199
199
|
* carries, and a field a consumer cannot bake is a pipeline with no input.
|
|
200
200
|
*/
|
|
201
201
|
export { bakeObjectSdf } from './bake/sdf.ts';
|
|
202
|
+
/*
|
|
203
|
+
* **The third time, and the one that got furthest before anybody noticed.** `bake/hlod.ts` builds
|
|
204
|
+
* the proxies and impostors `docs/CAPABILITIES.md` lists as shipping, it is tested, it is sized and
|
|
205
|
+
* it carries the licence — and until this line its only importer in the whole repository was its
|
|
206
|
+
* own test. A consumer following "the barrel is the contract" could read the row, believe the
|
|
207
|
+
* capability, and find no way to call it.
|
|
208
|
+
*
|
|
209
|
+
* The paragraph above says a demo boundary test caught the cluster case. Nothing caught this one,
|
|
210
|
+
* because no scene tried to bake an impostor — which is what the two paragraphs above are worth
|
|
211
|
+
* together: **a module reached only by its own test is not shipped, and no gate here asks.** Found
|
|
212
|
+
* by censusing what three consumers could adopt and what they could not.
|
|
213
|
+
*/
|
|
214
|
+
export {
|
|
215
|
+
IMPOSTOR_GUTTER,
|
|
216
|
+
IMPOSTOR_TILE,
|
|
217
|
+
PROXY_BASE_CELLS,
|
|
218
|
+
PROXY_MIN_CELLS,
|
|
219
|
+
buildImpostor,
|
|
220
|
+
buildProxy,
|
|
221
|
+
frameOf,
|
|
222
|
+
octahedralCoord,
|
|
223
|
+
octahedralDirection,
|
|
224
|
+
proxyResolution,
|
|
225
|
+
rasteriseView,
|
|
226
|
+
sampleImpostor,
|
|
227
|
+
} from './bake/hlod.ts';
|
|
228
|
+
export type { Impostor, ProxyCell, ViewFrame } from './bake/hlod.ts';
|
|
202
229
|
export type { ObjectSdf } from './bake/sdf.ts';
|
package/src/kn5.ts
CHANGED
|
@@ -430,6 +430,27 @@ export function readKn5Nodes(header: Kn5Header): { nodes: Kn5Node[]; meshes: Kn5
|
|
|
430
430
|
* this stays only for the warning, which is the thing a name genuinely can answer: a shader
|
|
431
431
|
* nobody here has seen is still geometry somebody wants.
|
|
432
432
|
*/
|
|
433
|
+
/**
|
|
434
|
+
* What a tested material's alpha reference actually is, where it states zero or states none.
|
|
435
|
+
*
|
|
436
|
+
* **Zero means the shader's own threshold, not "discard nothing".** A material that says it is
|
|
437
|
+
* alpha tested has already said that something is meant to be discarded, so a reference of zero
|
|
438
|
+
* cannot be read literally without contradicting the flag beside it. Assetto Corsa's `*AT*` shaders
|
|
439
|
+
* carry a built-in reference and a material overrides it by stating one; stating zero is how a
|
|
440
|
+
* material says it is not overriding anything.
|
|
441
|
+
*
|
|
442
|
+
* **A half, because that is the convention those shaders were authored against**, and because the
|
|
443
|
+
* masks in question are two-valued: a grille's hole and a seat's stitching are cut out of a texture
|
|
444
|
+
* whose alpha is 0 or 255, so any threshold strictly inside the range separates them identically.
|
|
445
|
+
* What would make this wrong is a material whose mask is a soft gradient, which wants blending
|
|
446
|
+
* rather than a test and says so with `alphaBlendMode`.
|
|
447
|
+
*/
|
|
448
|
+
const DEFAULT_ALPHA_REFERENCE = 0.5;
|
|
449
|
+
|
|
450
|
+
function alphaReference(stated: number): number {
|
|
451
|
+
return stated > 0 ? stated : DEFAULT_ALPHA_REFERENCE;
|
|
452
|
+
}
|
|
453
|
+
|
|
433
454
|
const KNOWN_SHADERS = new Set([
|
|
434
455
|
'ksPerPixelAlpha',
|
|
435
456
|
'ksWindscreen',
|
|
@@ -591,7 +612,7 @@ export function kn5ToMeshes(buffer: ArrayBuffer): Kn5Import {
|
|
|
591
612
|
* rather than on evidence — stated plainly for the same reason the bone block is read past
|
|
592
613
|
* rather than interpreted. What the change fixes is not this line but the one above it.
|
|
593
614
|
*/
|
|
594
|
-
cutout: material.alphaTested ? property('ksAlphaRef', 0) : 0,
|
|
615
|
+
cutout: material.alphaTested ? alphaReference(property('ksAlphaRef', 0)) : 0,
|
|
595
616
|
albedo: bind(material, 'txDiffuse'),
|
|
596
617
|
normalMap: bind(material, 'txNormal'),
|
|
597
618
|
/*
|