Jelajahi Sumber

[ts][pixi] Fix dark tint + alpha not working. Closes #2550.

Davide Tantillo 1 tahun lalu
induk
melakukan
cc6fc1f5b4

+ 1 - 0
spine-ts/spine-pixi/src/DarkSlotMesh.ts

@@ -99,6 +99,7 @@ export class DarkSlotMesh extends DarkTintMesh implements ISlotMesh {
 			this.tint = DarkSlotMesh.auxColor;
 			this.tint = DarkSlotMesh.auxColor;
 		}
 		}
 		this.blendMode = SpineTexture.toPixiBlending(slotBlendMode);
 		this.blendMode = SpineTexture.toPixiBlending(slotBlendMode);
+		this.alpha = DarkSlotMesh.auxColor[3];
 
 
 		if (this.geometry.indexBuffer.data.length !== finalIndices.length) {
 		if (this.geometry.indexBuffer.data.length !== finalIndices.length) {
 			this.geometry.indexBuffer.data = new Uint32Array(finalIndices);
 			this.geometry.indexBuffer.data = new Uint32Array(finalIndices);

+ 25 - 5
spine-ts/spine-pixi/src/Spine.ts

@@ -338,6 +338,20 @@ export class Spine extends Container {
 			pixiObject.mask = null;
 			pixiObject.mask = null;
 		}
 		}
 	}
 	}
+
+	/* 
+	* Colors in pixi are premultiplied.
+	* Pixi blending modes are modified to work with premultiplied colors. We cannot create custom blending modes.
+	* Textures are loaded as premultiplied (see assers/atlasLoader.ts: alphaMode: `page.pma ? ALPHA_MODES.PMA : ALPHA_MODES.UNPACK`):
+	* - textures non premultiplied are premultiplied on GPU on upload
+	* - textures premultiplied are uploaded on GPU as is since they are already premultiplied
+	* 
+	* We need to take this into consideration and calculates final colors for both light and dark color as if textures were always premultiplied.
+	* This implies for example that alpha for dark tint is always 1. This is way in DarkTintRenderer we have only the alpha of the light color.
+	* We implies alpha of dark color as 1 and just respective alpha byte to 1.
+	* (see DarkTintRenderer: const darkargb = (0xFF << 24) | darkTintRGB;)
+	* If we ever want to load texture as non premultiplied on GPU, we must add a new dark alpha parameter to the TintMaterial and set the alpha.
+	*/
 	private renderMeshes (): void {
 	private renderMeshes (): void {
 		this.resetMeshes();
 		this.resetMeshes();
 
 
@@ -403,15 +417,20 @@ export class Spine extends Container {
 				const slotColor = slot.color;
 				const slotColor = slot.color;
 				const alpha = skeletonColor.a * slotColor.a * attachmentColor.a;
 				const alpha = skeletonColor.a * slotColor.a * attachmentColor.a;
 				this.lightColor.set(
 				this.lightColor.set(
-					skeletonColor.r * slotColor.r * attachmentColor.r,
-					skeletonColor.g * slotColor.g * attachmentColor.g,
-					skeletonColor.b * slotColor.b * attachmentColor.b,
+					skeletonColor.r * slotColor.r * attachmentColor.r * alpha,
+					skeletonColor.g * slotColor.g * attachmentColor.g * alpha,
+					skeletonColor.b * slotColor.b * attachmentColor.b * alpha,
 					alpha
 					alpha
 				);
 				);
 				if (slot.darkColor != null) {
 				if (slot.darkColor != null) {
-					this.darkColor.setFromColor(slot.darkColor);
+					this.darkColor.set(
+						slot.darkColor.r * alpha,
+						slot.darkColor.g * alpha,
+						slot.darkColor.b * alpha,
+						1,
+					);
 				} else {
 				} else {
-					this.darkColor.set(0, 0, 0, 0);
+					this.darkColor.set(0, 0, 0, 1);
 				}
 				}
 
 
 				let finalVertices: NumberArrayLike;
 				let finalVertices: NumberArrayLike;
@@ -443,6 +462,7 @@ export class Spine extends Container {
 							verts[tempV++] = this.darkColor.r;
 							verts[tempV++] = this.darkColor.r;
 							verts[tempV++] = this.darkColor.g;
 							verts[tempV++] = this.darkColor.g;
 							verts[tempV++] = this.darkColor.b;
 							verts[tempV++] = this.darkColor.b;
+							verts[tempV++] = this.darkColor.a;
 						}
 						}
 					}
 					}
 					finalVertices = this.verticesCache;
 					finalVertices = this.verticesCache;

+ 7 - 2
spine-ts/spine-pixi/src/darkTintMesh/DarkTintRenderer.ts

@@ -99,8 +99,13 @@ export class DarkTintRenderer extends BatchRenderer {
 		const vertexData = element.vertexData;
 		const vertexData = element.vertexData;
 		const textureId = element._texture.baseTexture._batchLocation;
 		const textureId = element._texture.baseTexture._batchLocation;
 		const alpha = Math.min(element.worldAlpha, 1.0);
 		const alpha = Math.min(element.worldAlpha, 1.0);
-		const argb = Color.shared.setValue(element._tintRGB).toPremultiplied(alpha, (element._texture.baseTexture.alphaMode ?? 0) > 0);
-		const darkargb = Color.shared.setValue(element._darkTintRGB).toPremultiplied(alpha, (element._texture.baseTexture.alphaMode ?? 0) > 0);
+
+		const alphaInt = Math.round(alpha * 255) & 0xFF;
+		const tintRGB = element._tintRGB & 0xFFFFFF;
+		const argb = (alphaInt << 24) | tintRGB;
+
+		const darkTintRGB = element._darkTintRGB & 0xFFFFFF;
+		const darkargb = (0xFF << 24) | darkTintRGB;
 
 
 		// lets not worry about tint! for now..
 		// lets not worry about tint! for now..
 		for (let i = 0; i < vertexData.length; i += 2) {
 		for (let i = 0; i < vertexData.length; i += 2) {