puppet opacity
This commit is contained in:
@@ -9,12 +9,12 @@
|
||||
|
||||
let {
|
||||
puppets,
|
||||
frozenPuppetId,
|
||||
selectedPuppetId,
|
||||
onBoundsChange,
|
||||
skinHashes,
|
||||
}: {
|
||||
puppets: readonly PuppetState[];
|
||||
frozenPuppetId: string | null;
|
||||
selectedPuppetId: string | null;
|
||||
onBoundsChange: (bounds: PuppetScreenBounds[]) => void;
|
||||
skinHashes: ReadonlyMap<string, string | null>;
|
||||
} = $props();
|
||||
@@ -38,7 +38,8 @@
|
||||
puppetManager.update(
|
||||
puppets,
|
||||
$sceneConfiguration.puppetScale,
|
||||
frozenPuppetId,
|
||||
$sceneConfiguration.puppetOpacity,
|
||||
selectedPuppetId,
|
||||
clock.getDelta(),
|
||||
clock.getElapsed(),
|
||||
skinHashes,
|
||||
|
||||
@@ -54,8 +54,10 @@ export class Puppet {
|
||||
deltaSeconds: number,
|
||||
elapsedSeconds: number,
|
||||
skinHash: string | null,
|
||||
opacity: number,
|
||||
) {
|
||||
this.skin.update(skinHash);
|
||||
this.skin.setOpacity(opacity);
|
||||
if (frozen) {
|
||||
this.animation.pause();
|
||||
return;
|
||||
@@ -77,11 +79,12 @@ export class Puppet {
|
||||
dispose() {
|
||||
this.skin.dispose();
|
||||
|
||||
const geometries = new Set<THREE.BufferGeometry>();
|
||||
this.root.traverse((object) => {
|
||||
if (!(object instanceof THREE.Mesh)) return;
|
||||
|
||||
object.geometry.dispose();
|
||||
geometries.add(object.geometry);
|
||||
});
|
||||
for (const geometry of geometries) geometry.dispose();
|
||||
}
|
||||
|
||||
private createRig(): PuppetRig {
|
||||
|
||||
@@ -11,7 +11,8 @@ export class PuppetManager {
|
||||
update(
|
||||
states: readonly PuppetState[],
|
||||
scale: number,
|
||||
frozenPuppetId: string | null,
|
||||
idleOpacity: number,
|
||||
selectedPuppetId: string | null,
|
||||
deltaSeconds: number,
|
||||
elapsedSeconds: number,
|
||||
skinHashes: ReadonlyMap<string, string | null>,
|
||||
@@ -24,10 +25,11 @@ export class PuppetManager {
|
||||
?.update(
|
||||
state,
|
||||
this.world,
|
||||
state.id === frozenPuppetId,
|
||||
state.id === selectedPuppetId,
|
||||
deltaSeconds,
|
||||
elapsedSeconds,
|
||||
skinHashes.get(state.id) ?? null,
|
||||
state.id === selectedPuppetId ? 1 : idleOpacity,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ function loadTexture(url: string) {
|
||||
|
||||
export class PuppetSkin {
|
||||
private readonly material: THREE.MeshStandardMaterial;
|
||||
private readonly depthMaterial: THREE.MeshBasicMaterial;
|
||||
private texture: THREE.Texture | null = null;
|
||||
private requestedHash: string | null | undefined;
|
||||
private requestId = 0;
|
||||
@@ -130,6 +131,14 @@ export class PuppetSkin {
|
||||
color: "white",
|
||||
transparent: true,
|
||||
alphaTest: 0.5,
|
||||
depthWrite: false,
|
||||
depthFunc: THREE.EqualDepth,
|
||||
});
|
||||
this.depthMaterial = new THREE.MeshBasicMaterial({
|
||||
colorWrite: false,
|
||||
depthWrite: true,
|
||||
depthTest: true,
|
||||
alphaTest: 0.5,
|
||||
});
|
||||
const parts: SkinPart[] = [
|
||||
{ mesh: rig.head, faces: HEAD },
|
||||
@@ -142,6 +151,11 @@ export class PuppetSkin {
|
||||
for (const part of parts) {
|
||||
part.mesh.material = this.material;
|
||||
applyUvs(part.mesh.geometry, part.faces);
|
||||
|
||||
// Opaque-phase depth establishes the nearest rig surface before the
|
||||
// translucent parent mesh contributes color.
|
||||
const depthMesh = new THREE.Mesh(part.mesh.geometry, this.depthMaterial);
|
||||
part.mesh.add(depthMesh);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,16 +175,25 @@ export class PuppetSkin {
|
||||
this.texture?.dispose();
|
||||
this.texture = texture;
|
||||
this.material.map = texture;
|
||||
this.depthMaterial.map = texture;
|
||||
this.material.needsUpdate = true;
|
||||
this.depthMaterial.needsUpdate = true;
|
||||
})
|
||||
.catch((error) =>
|
||||
console.error(`Failed to load skin for ${this.userId}`, error),
|
||||
);
|
||||
}
|
||||
|
||||
setOpacity(opacity: number) {
|
||||
if (this.material.opacity === opacity) return;
|
||||
this.material.opacity = opacity;
|
||||
this.material.alphaTest = opacity * 0.5;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.requestId++;
|
||||
this.texture?.dispose();
|
||||
this.material.dispose();
|
||||
this.depthMaterial.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user