@plasius/gpu-renderer 0.2.54 → 0.2.56
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/CHANGELOG.md +30 -0
- package/README.md +7 -0
- package/dist/index.cjs +21 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +21 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/canonical-wavefront-meshes.js +11 -10
- package/src/index.d.ts +5 -0
- package/src/wavefront-mesh-sources.js +3 -3
- package/src/wavefront-scene-normalizers.js +10 -1
- package/src/wavefront-shader-materials.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -23,6 +23,34 @@ All notable changes to this project will be documented in this file.
|
|
|
23
23
|
- **Security**
|
|
24
24
|
- (placeholder)
|
|
25
25
|
|
|
26
|
+
## [0.2.56] - 2026-10-24
|
|
27
|
+
|
|
28
|
+
- **Added**
|
|
29
|
+
- (placeholder)
|
|
30
|
+
|
|
31
|
+
- **Changed**
|
|
32
|
+
- (placeholder)
|
|
33
|
+
|
|
34
|
+
- **Fixed**
|
|
35
|
+
- Reject referenced canonical unlit workflows and declared unlit extension markers until an explicit unlit shading path exists, with a bounded diagnostic that preserves the caller's previous supported rendering path.
|
|
36
|
+
|
|
37
|
+
- **Security**
|
|
38
|
+
- (placeholder)
|
|
39
|
+
|
|
40
|
+
## [0.2.55] - 2026-10-24
|
|
41
|
+
|
|
42
|
+
- **Added**
|
|
43
|
+
- (placeholder)
|
|
44
|
+
|
|
45
|
+
- **Changed**
|
|
46
|
+
- (placeholder)
|
|
47
|
+
|
|
48
|
+
- **Fixed**
|
|
49
|
+
- Preserve canonical blend alpha exactly once and ignore factor/texture alpha for opaque materials through CPU/GPU packing and material sampling; retain legacy Wavefront alpha composition when mode is omitted.
|
|
50
|
+
|
|
51
|
+
- **Security**
|
|
52
|
+
- (placeholder)
|
|
53
|
+
|
|
26
54
|
## [0.2.54] - 2026-10-21
|
|
27
55
|
|
|
28
56
|
- **Added**
|
|
@@ -1300,3 +1328,5 @@ All notable changes to this project will be documented in this file.
|
|
|
1300
1328
|
[0.2.52]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.2.52
|
|
1301
1329
|
[0.2.53]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.2.53
|
|
1302
1330
|
[0.2.54]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.2.54
|
|
1331
|
+
[0.2.55]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.2.55
|
|
1332
|
+
[0.2.56]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.2.56
|
package/README.md
CHANGED
|
@@ -74,6 +74,13 @@ The canonical adapter maps the core 0.5 material texture slots; it currently
|
|
|
74
74
|
accepts UV0 and identity texture transforms. Other selections/transforms fail
|
|
75
75
|
explicitly so authored appearance is not silently changed. See the
|
|
76
76
|
[canonical integration contract](docs/guides/integration.md#canonical-model-ingestion).
|
|
77
|
+
Canonical blend materials multiply authored factor alpha by texture alpha once;
|
|
78
|
+
opaque materials ignore both alpha channels. Direct `WavefrontMeshInput` callers
|
|
79
|
+
can select `alphaMode: "opaque" | "blend"`; omitting it preserves legacy opacity
|
|
80
|
+
composition. Alpha masks remain unsupported by the canonical adapter.
|
|
81
|
+
Referenced canonical unlit workflows and declared `KHR_materials_unlit`/`unlit`
|
|
82
|
+
extension markers are unsupported and fail explicitly. Keep those assets on an
|
|
83
|
+
unlit-capable rendering path; do not drop their markers or reinterpret them as lit.
|
|
77
84
|
For an interactive model viewer with loading, integrity checks, camera gestures
|
|
78
85
|
and quality controls, use the shared package's `model-inspection` entry.
|
|
79
86
|
|
package/dist/index.cjs
CHANGED
|
@@ -1654,14 +1654,6 @@ function textureSample(binding, textures, label, extra = {}) {
|
|
|
1654
1654
|
}
|
|
1655
1655
|
function cloneMaterialExtensions(material, textures) {
|
|
1656
1656
|
const extensions = { ...material.extensions ?? {} };
|
|
1657
|
-
if (material.workflow === "unlit") {
|
|
1658
|
-
const unlitKey = "KHR_materials_unlit";
|
|
1659
|
-
const unlitValue = extensions[unlitKey] ?? extensions.unlit ?? {};
|
|
1660
|
-
if (typeof unlitValue !== "object" || unlitValue === null || Array.isArray(unlitValue)) {
|
|
1661
|
-
throw new TypeError(`Canonical material extension ${unlitKey} must be an object.`);
|
|
1662
|
-
}
|
|
1663
|
-
extensions[unlitKey] = { ...unlitValue, enabled: true };
|
|
1664
|
-
}
|
|
1665
1657
|
for (const [bindingName, extensionName, textureKey] of EXTENSION_TEXTURE_BINDINGS) {
|
|
1666
1658
|
const binding = material.textures?.[bindingName];
|
|
1667
1659
|
if (!binding) {
|
|
@@ -1686,17 +1678,22 @@ function mapMaterial(material, materialRefId, textures) {
|
|
|
1686
1678
|
if (material.alphaMode === "mask") {
|
|
1687
1679
|
throw new Error("Canonical alphaMode mask is unsupported by WavefrontMeshInput.");
|
|
1688
1680
|
}
|
|
1689
|
-
if (material.workflow
|
|
1681
|
+
if (material.workflow === "unlit" || Object.hasOwn(material.extensions ?? {}, "KHR_materials_unlit") || Object.hasOwn(material.extensions ?? {}, "unlit")) {
|
|
1682
|
+
throw new Error("Canonical unlit materials are unsupported by WavefrontMeshInput; retain an unlit-capable rendering path.");
|
|
1683
|
+
}
|
|
1684
|
+
if (material.workflow !== "metallic-roughness") {
|
|
1690
1685
|
throw new Error(`Unsupported canonical material workflow: ${material.workflow}.`);
|
|
1691
1686
|
}
|
|
1692
1687
|
const mapped = {
|
|
1693
1688
|
materialRefId,
|
|
1689
|
+
alphaMode: material.alphaMode,
|
|
1694
1690
|
...material.alphaMode === "blend" ? { materialKind: "transparent" } : {},
|
|
1695
1691
|
baseColor: material.baseColorFactor,
|
|
1696
1692
|
emission: material.emissiveFactor ? [...material.emissiveFactor, 1] : [0, 0, 0, 1],
|
|
1697
1693
|
roughness: material.roughnessFactor,
|
|
1698
1694
|
metallic: material.metallicFactor,
|
|
1699
|
-
|
|
1695
|
+
// The authored factor remains in baseColor.a; do not multiply it twice.
|
|
1696
|
+
opacity: 1,
|
|
1700
1697
|
clearcoat: material.clearcoatFactor,
|
|
1701
1698
|
clearcoatRoughness: material.clearcoatRoughnessFactor,
|
|
1702
1699
|
transmission: material.transmissionFactor,
|
|
@@ -8377,7 +8374,7 @@ fn sample_surface_material(
|
|
|
8377
8374
|
let baseColorTexel = sample_atlas(baseColorAtlasTexture, triangle.baseColorAtlas, uv);
|
|
8378
8375
|
let baseColor = vec4<f32>(
|
|
8379
8376
|
clamp(triangle.color.rgb * srgb_to_linear_vec3(baseColorTexel.rgb), vec3<f32>(0.0), vec3<f32>(1.0)),
|
|
8380
|
-
clamp(triangle.color.a * baseColorTexel.a, 0.0, 1.0)
|
|
8377
|
+
select(clamp(triangle.color.a * baseColorTexel.a, 0.0, 1.0), 1.0, triangle.textureSettings.w > 0.5)
|
|
8381
8378
|
);
|
|
8382
8379
|
let metallicRoughnessTexel = sample_atlas(
|
|
8383
8380
|
metallicRoughnessAtlasTexture,
|
|
@@ -9361,6 +9358,10 @@ function createDefaultWavefrontSceneObjects() {
|
|
|
9361
9358
|
]);
|
|
9362
9359
|
}
|
|
9363
9360
|
function normalizeWavefrontMesh(input = {}, meshIndex = 0) {
|
|
9361
|
+
const alphaMode = input.alphaMode;
|
|
9362
|
+
if (alphaMode !== void 0 && alphaMode !== "opaque" && alphaMode !== "blend") {
|
|
9363
|
+
throw new TypeError("mesh alphaMode must be opaque or blend.");
|
|
9364
|
+
}
|
|
9364
9365
|
const positions = input.positions;
|
|
9365
9366
|
const positionLength = getArrayLikeLength(positions);
|
|
9366
9367
|
if (positionLength < 9 || positionLength % 3 !== 0) {
|
|
@@ -9390,7 +9391,11 @@ function normalizeWavefrontMesh(input = {}, meshIndex = 0) {
|
|
|
9390
9391
|
input.emission ?? input.emissive ?? input.material?.emission ?? input.material?.emissive,
|
|
9391
9392
|
[0, 0, 0, 1]
|
|
9392
9393
|
);
|
|
9393
|
-
const opacity =
|
|
9394
|
+
const opacity = alphaMode === "opaque" ? 1 : clamp2(
|
|
9395
|
+
readFiniteNumber("opacity", input.opacity ?? input.material?.opacity, alphaMode === "blend" ? 1 : color[3] ?? 1),
|
|
9396
|
+
0,
|
|
9397
|
+
1
|
|
9398
|
+
);
|
|
9394
9399
|
const transmission = clamp2(
|
|
9395
9400
|
readFiniteNumber("transmission", input.transmission ?? input.material?.transmission, materialExtensions.transmission),
|
|
9396
9401
|
0,
|
|
@@ -9422,6 +9427,7 @@ function normalizeWavefrontMesh(input = {}, meshIndex = 0) {
|
|
|
9422
9427
|
0
|
|
9423
9428
|
),
|
|
9424
9429
|
medium,
|
|
9430
|
+
alphaMode,
|
|
9425
9431
|
color: Object.freeze(color),
|
|
9426
9432
|
emission: Object.freeze(emission),
|
|
9427
9433
|
roughness: clamp2(readFiniteNumber("roughness", input.roughness ?? input.material?.roughness, 0.72), 0, 1),
|
|
@@ -9573,7 +9579,7 @@ function createMeshTriangleRecords(meshes, gpuMaterialSource = null) {
|
|
|
9573
9579
|
clampUnit(mesh.normalTexture?.scale ?? mesh.normalTexture?.strength ?? 1),
|
|
9574
9580
|
clampUnit(mesh.occlusionTexture?.strength ?? 1),
|
|
9575
9581
|
clampUnit(mesh.emissiveTexture?.strength ?? 1),
|
|
9576
|
-
0
|
|
9582
|
+
mesh.alphaMode === "opaque" ? 1 : 0
|
|
9577
9583
|
]),
|
|
9578
9584
|
extensionTextures: Object.freeze(
|
|
9579
9585
|
Object.fromEntries(
|
|
@@ -9916,7 +9922,7 @@ function createWavefrontGpuMaterialSource(meshes = []) {
|
|
|
9916
9922
|
clampUnit(mesh.normalTexture?.scale ?? mesh.normalTexture?.strength ?? 1),
|
|
9917
9923
|
clampUnit(mesh.occlusionTexture?.strength ?? 1),
|
|
9918
9924
|
clampUnit(mesh.emissiveTexture?.strength ?? 1),
|
|
9919
|
-
0
|
|
9925
|
+
mesh.alphaMode === "opaque" ? 1 : 0
|
|
9920
9926
|
]);
|
|
9921
9927
|
});
|
|
9922
9928
|
return Object.freeze({
|
|
@@ -10101,7 +10107,7 @@ function createWavefrontGpuMeshSource(meshes = [], gpuMaterialSourceInput = null
|
|
|
10101
10107
|
clampUnit(mesh.normalTexture?.scale ?? mesh.normalTexture?.strength ?? 1),
|
|
10102
10108
|
clampUnit(mesh.occlusionTexture?.strength ?? 1),
|
|
10103
10109
|
clampUnit(mesh.emissiveTexture?.strength ?? 1),
|
|
10104
|
-
0
|
|
10110
|
+
mesh.alphaMode === "opaque" ? 1 : 0
|
|
10105
10111
|
]);
|
|
10106
10112
|
vertexCursor += meshVertexCount;
|
|
10107
10113
|
indexCursor += mesh.indices.length;
|