[webgl] Fix blend modes, see #2025, #2347

This commit is contained in:
Mario Zechner 2023-09-13 22:26:27 +02:00
parent d5326a9823
commit a397b8fe3f
4 changed files with 27 additions and 55 deletions

View File

@ -27,7 +27,7 @@
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
import { Color, Disposable, TimeKeeper } from "@esotericsoftware/spine-core"; import { BlendMode, Color, Disposable, TimeKeeper } from "@esotericsoftware/spine-core";
import { GLTexture } from "./GLTexture"; import { GLTexture } from "./GLTexture";
import { ResizeMode, SceneRenderer } from "./SceneRenderer"; import { ResizeMode, SceneRenderer } from "./SceneRenderer";
@ -88,7 +88,7 @@ export class LoadingScreen implements Disposable {
renderer.resize(ResizeMode.Expand); renderer.resize(ResizeMode.Expand);
renderer.camera.position.set(canvas.width / 2, canvas.height / 2, 0); renderer.camera.position.set(canvas.width / 2, canvas.height / 2, 0);
renderer.batcher.setBlendMode(gl.ONE, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); renderer.batcher.setBlendMode(BlendMode.Normal, true);
if (complete) { if (complete) {
this.fadeOut += this.timeKeeper.delta * (this.timeKeeper.totalTime < 1 ? 2 : 1); this.fadeOut += this.timeKeeper.delta * (this.timeKeeper.totalTime < 1 ? 2 : 1);

View File

@ -27,12 +27,19 @@
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
import { Disposable } from "@esotericsoftware/spine-core"; import { BlendMode, Disposable } from "@esotericsoftware/spine-core";
import { GLTexture } from "./GLTexture"; import { GLTexture } from "./GLTexture";
import { Mesh, Position2Attribute, ColorAttribute, TexCoordAttribute, Color2Attribute } from "./Mesh"; import { Mesh, Position2Attribute, ColorAttribute, TexCoordAttribute, Color2Attribute } from "./Mesh";
import { Shader } from "./Shader"; import { Shader } from "./Shader";
import { ManagedWebGLRenderingContext } from "./WebGL"; import { ManagedWebGLRenderingContext } from "./WebGL";
const GL_ONE = 1;
const GL_ONE_MINUS_SRC_COLOR = 0x0301;
const GL_SRC_ALPHA = 0x0302;
const GL_ONE_MINUS_SRC_ALPHA = 0x0303;
const GL_ONE_MINUS_DST_ALPHA = 0x0305;
const GL_DST_COLOR = 0x0306;
export class PolygonBatcher implements Disposable { export class PolygonBatcher implements Disposable {
public static disableCulling = false; public static disableCulling = false;
@ -80,16 +87,28 @@ export class PolygonBatcher implements Disposable {
} }
} }
setBlendMode (srcColorBlend: number, srcAlphaBlend: number, dstBlend: number) { private static blendModesGL: {srcRgb: number, srcRgbPma: number, dstRgb: number, srcAlpha: number}[] = [
{srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE },
{srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE, srcAlpha: GL_ONE },
{srcRgb: GL_DST_COLOR, srcRgbPma: GL_DST_COLOR, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE},
{srcRgb: GL_ONE, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_COLOR, srcAlpha: GL_ONE }
]
setBlendMode (blendMode: BlendMode, premultipliedAlpha: boolean) {
const blendModeGL = PolygonBatcher.blendModesGL[blendMode];
const srcColorBlend = premultipliedAlpha ? blendModeGL.srcRgbPma : blendModeGL.srcRgb;
const srcAlphaBlend = blendModeGL.srcAlpha;
const dstBlend = blendModeGL.dstRgb;
if (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstBlend == dstBlend) return; if (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstBlend == dstBlend) return;
this.srcColorBlend = srcColorBlend; this.srcColorBlend = srcColorBlend;
this.srcAlphaBlend = srcAlphaBlend; this.srcAlphaBlend = srcAlphaBlend;
this.dstBlend = dstBlend; this.dstBlend = dstBlend;
if (this.isDrawing) { if (this.isDrawing) {
this.flush(); this.flush();
let gl = this.context.gl;
gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend);
} }
let gl = this.context.gl;
gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend);
} }
draw (texture: GLTexture, vertices: ArrayLike<number>, indices: Array<number>) { draw (texture: GLTexture, vertices: ArrayLike<number>, indices: Array<number>) {

View File

@ -30,7 +30,7 @@
import { NumberArrayLike, Color, SkeletonClipping, Vector2, Utils, Skeleton, BlendMode, RegionAttachment, TextureAtlasRegion, MeshAttachment, ClippingAttachment } from "@esotericsoftware/spine-core"; import { NumberArrayLike, Color, SkeletonClipping, Vector2, Utils, Skeleton, BlendMode, RegionAttachment, TextureAtlasRegion, MeshAttachment, ClippingAttachment } from "@esotericsoftware/spine-core";
import { GLTexture } from "./GLTexture"; import { GLTexture } from "./GLTexture";
import { PolygonBatcher } from "./PolygonBatcher"; import { PolygonBatcher } from "./PolygonBatcher";
import { ManagedWebGLRenderingContext, WebGLBlendModeConverter } from "./WebGL"; import { ManagedWebGLRenderingContext } from "./WebGL";
class Renderable { class Renderable {
@ -68,11 +68,6 @@ export class SkeletonRenderer {
let twoColorTint = this.twoColorTint; let twoColorTint = this.twoColorTint;
let blendMode: BlendMode | null = null; let blendMode: BlendMode | null = null;
let tempPos = this.temp;
let tempUv = this.temp2;
let tempLight = this.temp3;
let tempDark = this.temp4;
let renderable: Renderable = this.renderable; let renderable: Renderable = this.renderable;
let uvs: NumberArrayLike; let uvs: NumberArrayLike;
let triangles: Array<number>; let triangles: Array<number>;
@ -166,10 +161,7 @@ export class SkeletonRenderer {
let slotBlendMode = slot.data.blendMode; let slotBlendMode = slot.data.blendMode;
if (slotBlendMode != blendMode) { if (slotBlendMode != blendMode) {
blendMode = slotBlendMode; blendMode = slotBlendMode;
batcher.setBlendMode( batcher.setBlendMode(blendMode, premultipliedAlpha);
WebGLBlendModeConverter.getSourceColorGLBlendMode(blendMode, premultipliedAlpha),
WebGLBlendModeConverter.getSourceAlphaGLBlendMode(blendMode),
WebGLBlendModeConverter.getDestGLBlendMode(blendMode));
} }
if (clipper.isClipping()) { if (clipper.isClipping()) {

View File

@ -62,42 +62,3 @@ export class ManagedWebGLRenderingContext {
if (index > -1) this.restorables.splice(index, 1); if (index > -1) this.restorables.splice(index, 1);
} }
} }
const ONE = 1;
const ONE_MINUS_SRC_COLOR = 0x0301;
const SRC_ALPHA = 0x0302;
const ONE_MINUS_SRC_ALPHA = 0x0303;
const ONE_MINUS_DST_ALPHA = 0x0305;
const DST_COLOR = 0x0306;
export class WebGLBlendModeConverter {
static getDestGLBlendMode (blendMode: BlendMode) {
switch (blendMode) {
case BlendMode.Normal: return ONE_MINUS_SRC_ALPHA;
case BlendMode.Additive: return ONE;
case BlendMode.Multiply: return ONE_MINUS_SRC_ALPHA;
case BlendMode.Screen: return ONE_MINUS_SRC_ALPHA;
default: throw new Error("Unknown blend mode: " + blendMode);
}
}
static getSourceColorGLBlendMode (blendMode: BlendMode, premultipliedAlpha: boolean = false) {
switch (blendMode) {
case BlendMode.Normal: return premultipliedAlpha ? ONE : SRC_ALPHA;
case BlendMode.Additive: return premultipliedAlpha ? ONE : SRC_ALPHA;
case BlendMode.Multiply: return DST_COLOR;
case BlendMode.Screen: return ONE;
default: throw new Error("Unknown blend mode: " + blendMode);
}
}
static getSourceAlphaGLBlendMode (blendMode: BlendMode) {
switch (blendMode) {
case BlendMode.Normal: return ONE;
case BlendMode.Additive: return ONE;
case BlendMode.Multiply: return ONE_MINUS_SRC_ALPHA;
case BlendMode.Screen: return ONE_MINUS_SRC_COLOR;
default: throw new Error("Unknown blend mode: " + blendMode);
}
}
}