@plasius/gpu-renderer 0.2.54 → 0.2.55

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plasius/gpu-renderer",
3
- "version": "0.2.54",
3
+ "version": "0.2.55",
4
4
  "description": "Framework-agnostic WebGPU renderer runtime for Plasius projects.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -124,6 +124,7 @@ function mapMaterial(material, materialRefId, textures) {
124
124
 
125
125
  const mapped = {
126
126
  materialRefId,
127
+ alphaMode: material.alphaMode,
127
128
  ...(material.alphaMode === "blend" ? { materialKind: "transparent" } : {}),
128
129
  baseColor: material.baseColorFactor,
129
130
  emission: material.emissiveFactor
@@ -131,7 +132,8 @@ function mapMaterial(material, materialRefId, textures) {
131
132
  : [0, 0, 0, 1],
132
133
  roughness: material.roughnessFactor,
133
134
  metallic: material.metallicFactor,
134
- opacity: material.alphaMode === "opaque" ? 1 : material.baseColorFactor?.[3],
135
+ // The authored factor remains in baseColor.a; do not multiply it twice.
136
+ opacity: 1,
135
137
  clearcoat: material.clearcoatFactor,
136
138
  clearcoatRoughness: material.clearcoatRoughnessFactor,
137
139
  transmission: material.transmissionFactor,
package/src/index.d.ts CHANGED
@@ -522,6 +522,9 @@ export interface WavefrontSceneObject {
522
522
  }
523
523
 
524
524
  export interface WavefrontMeshInput {
525
+ /** Opaque ignores factor/texture alpha. Blend defaults opacity to one.
526
+ * Omitted preserves legacy factor × opacity × texture alpha semantics. */
527
+ readonly alphaMode?: "opaque" | "blend";
525
528
  readonly id?: number;
526
529
  readonly positions: readonly number[] | Float32Array;
527
530
  readonly indices?: readonly number[] | Uint16Array | Uint32Array;
@@ -749,6 +752,7 @@ export interface WavefrontGpuMeshSource {
749
752
  readonly roughness: number;
750
753
  readonly metallic: number;
751
754
  readonly opacity: number;
755
+ readonly alphaMode?: "opaque" | "blend";
752
756
  readonly ior: number;
753
757
  readonly sheen: number;
754
758
  readonly sheenTint: number;
@@ -1416,6 +1420,7 @@ export function normalizeWavefrontMesh(
1416
1420
  roughness: number;
1417
1421
  metallic: number;
1418
1422
  opacity: number;
1423
+ alphaMode?: "opaque" | "blend";
1419
1424
  ior: number;
1420
1425
  sheen: number;
1421
1426
  sheenTint: number;
@@ -121,7 +121,7 @@ function createMeshTriangleRecords(meshes, gpuMaterialSource = null) {
121
121
  clampUnit(mesh.normalTexture?.scale ?? mesh.normalTexture?.strength ?? 1),
122
122
  clampUnit(mesh.occlusionTexture?.strength ?? 1),
123
123
  clampUnit(mesh.emissiveTexture?.strength ?? 1),
124
- 0,
124
+ mesh.alphaMode === "opaque" ? 1 : 0,
125
125
  ]),
126
126
  extensionTextures: Object.freeze(
127
127
  Object.fromEntries(
@@ -499,7 +499,7 @@ export function createWavefrontGpuMaterialSource(meshes = []) {
499
499
  clampUnit(mesh.normalTexture?.scale ?? mesh.normalTexture?.strength ?? 1),
500
500
  clampUnit(mesh.occlusionTexture?.strength ?? 1),
501
501
  clampUnit(mesh.emissiveTexture?.strength ?? 1),
502
- 0,
502
+ mesh.alphaMode === "opaque" ? 1 : 0,
503
503
  ]);
504
504
  });
505
505
 
@@ -705,7 +705,7 @@ export function createWavefrontGpuMeshSource(meshes = [], gpuMaterialSourceInput
705
705
  clampUnit(mesh.normalTexture?.scale ?? mesh.normalTexture?.strength ?? 1),
706
706
  clampUnit(mesh.occlusionTexture?.strength ?? 1),
707
707
  clampUnit(mesh.emissiveTexture?.strength ?? 1),
708
- 0,
708
+ mesh.alphaMode === "opaque" ? 1 : 0,
709
709
  ]);
710
710
 
711
711
  vertexCursor += meshVertexCount;
@@ -193,6 +193,10 @@ export function createDefaultWavefrontSceneObjects() {
193
193
  }
194
194
 
195
195
  export function normalizeWavefrontMesh(input = {}, meshIndex = 0) {
196
+ const alphaMode = input.alphaMode;
197
+ if (alphaMode !== undefined && alphaMode !== "opaque" && alphaMode !== "blend") {
198
+ throw new TypeError("mesh alphaMode must be opaque or blend.");
199
+ }
196
200
  const positions = input.positions;
197
201
  const positionLength = getArrayLikeLength(positions);
198
202
  if (positionLength < 9 || positionLength % 3 !== 0) {
@@ -236,7 +240,11 @@ export function normalizeWavefrontMesh(input = {}, meshIndex = 0) {
236
240
  input.emission ?? input.emissive ?? input.material?.emission ?? input.material?.emissive,
237
241
  [0, 0, 0, 1]
238
242
  );
239
- const opacity = clamp(readFiniteNumber("opacity", input.opacity ?? input.material?.opacity, color[3] ?? 1), 0, 1);
243
+ const opacity = alphaMode === "opaque" ? 1 : clamp(
244
+ readFiniteNumber("opacity", input.opacity ?? input.material?.opacity, alphaMode === "blend" ? 1 : color[3] ?? 1),
245
+ 0,
246
+ 1
247
+ );
240
248
  const transmission = clamp(
241
249
  readFiniteNumber("transmission", input.transmission ?? input.material?.transmission, materialExtensions.transmission),
242
250
  0,
@@ -280,6 +288,7 @@ export function normalizeWavefrontMesh(input = {}, meshIndex = 0) {
280
288
  0
281
289
  ),
282
290
  medium,
291
+ alphaMode,
283
292
  color: Object.freeze(color),
284
293
  emission: Object.freeze(emission),
285
294
  roughness: clamp(readFiniteNumber("roughness", input.roughness ?? input.material?.roughness, 0.72), 0, 1),
@@ -67,7 +67,7 @@ fn sample_surface_material(
67
67
  let baseColorTexel = sample_atlas(baseColorAtlasTexture, triangle.baseColorAtlas, uv);
68
68
  let baseColor = vec4<f32>(
69
69
  clamp(triangle.color.rgb * srgb_to_linear_vec3(baseColorTexel.rgb), vec3<f32>(0.0), vec3<f32>(1.0)),
70
- clamp(triangle.color.a * baseColorTexel.a, 0.0, 1.0)
70
+ select(clamp(triangle.color.a * baseColorTexel.a, 0.0, 1.0), 1.0, triangle.textureSettings.w > 0.5)
71
71
  );
72
72
  let metallicRoughnessTexel = sample_atlas(
73
73
  metallicRoughnessAtlasTexture,