From 6994fa6be878aa2fa05374695c3d96d6d6bf6ebf Mon Sep 17 00:00:00 2001 From: ww-rm Date: Fri, 4 Apr 2025 11:26:23 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dshader=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SpineViewer/Spine/BlendModeSFML.cs | 86 +++++++++++++++---- .../Spine/Implementations/Spine/Spine21.cs | 13 +-- .../Spine/Implementations/Spine/Spine36.cs | 19 ++-- .../Spine/Implementations/Spine/Spine37.cs | 20 ++--- .../Spine/Implementations/Spine/Spine38.cs | 22 ++--- .../Spine/Implementations/Spine/Spine40.cs | 20 ++--- .../Spine/Implementations/Spine/Spine41.cs | 20 ++--- .../Spine/Implementations/Spine/Spine42.cs | 20 ++--- SpineViewer/Spine/Shader.cs | 53 ++++++++++-- 9 files changed, 147 insertions(+), 126 deletions(-) diff --git a/SpineViewer/Spine/BlendModeSFML.cs b/SpineViewer/Spine/BlendModeSFML.cs index a8142bb..f89d1bd 100644 --- a/SpineViewer/Spine/BlendModeSFML.cs +++ b/SpineViewer/Spine/BlendModeSFML.cs @@ -7,36 +7,86 @@ using System.Threading.Tasks; namespace SpineViewer.Spine { /// - /// SFML 混合模式 + /// SFML 混合模式, 预乘模式下输入和输出的像素值都是预乘的 /// public static class BlendModeSFML { - /// - /// Alpha Blend - /// - /// res.c = src.c * src.a + dst.c * (1 - src.a) - /// res.a = src.a * 1 + dst.a * (1 - src.a) - /// - /// - public static SFML.Graphics.BlendMode Normal = SFML.Graphics.BlendMode.Alpha; + ///// + ///// Normal Blend, 无预乘, 仅在 dst.a 是 1 时得到正确结果, 其余情况是有偏结果 + ///// src.c < dst.c 时, 结果偏大, 例如 src 是半透明纯黑, dst 是全透明纯白 + ///// src.c > dst.c 时, 结果偏小, 例如 src 是半透明纯白, dst 是全透明纯黑 + ///// + ///// res.c = src.c * src.a + dst.c * (1 - src.a) + ///// res.a = src.a * 1 + dst.a * (1 - src.a) + ///// + ///// + //public static SFML.Graphics.BlendMode Normal = new( + // SFML.Graphics.BlendMode.Factor.SrcAlpha, + // SFML.Graphics.BlendMode.Factor.OneMinusSrcAlpha, + // SFML.Graphics.BlendMode.Equation.Add, + // SFML.Graphics.BlendMode.Factor.One, + // SFML.Graphics.BlendMode.Factor.OneMinusSrcAlpha, + // SFML.Graphics.BlendMode.Equation.Add + //); + + ///// + ///// Additive Blend, 无预乘, 仅在 dst.a 是 1 时得到正确结果, 其余情况是有偏结果 + ///// src.a + dst.a >= 1 时, 结果偏大, 例如 src 是不透明纯黑, dst 是全透明纯白 + ///// src.a + dst.a < 1 时, 结果偏差方式类似 , 均可假设 dst 是全透明纯白进行判断 + ///// + ///// res.c = src.c * src.a + dst.c * 1 + ///// res.a = src.a * 1 + dst.a * 1 + ///// + ///// + //public static SFML.Graphics.BlendMode Additive = new( + // SFML.Graphics.BlendMode.Factor.SrcAlpha, + // SFML.Graphics.BlendMode.Factor.One, + // SFML.Graphics.BlendMode.Equation.Add, + // SFML.Graphics.BlendMode.Factor.One, + // SFML.Graphics.BlendMode.Factor.One, + // SFML.Graphics.BlendMode.Equation.Add + //); /// - /// Additive Blend + /// Normal Blend with PremultipliedAlpha /// - /// res.c = src.c * src.a + dst.c * 1 - /// res.a = src.a * 1 + dst.a * 1 + /// [res.c * res.a] = [src.c * src.a] * 1 + [dst.c * dst.a] * (1 - src.a) + /// res.a = src.a * 1 + dst.a * (1 - src.a) /// /// - public static SFML.Graphics.BlendMode Additive = SFML.Graphics.BlendMode.Add; + public static SFML.Graphics.BlendMode NormalPma = new( + SFML.Graphics.BlendMode.Factor.One, + SFML.Graphics.BlendMode.Factor.OneMinusSrcAlpha, + SFML.Graphics.BlendMode.Equation.Add, + SFML.Graphics.BlendMode.Factor.One, + SFML.Graphics.BlendMode.Factor.OneMinusSrcAlpha, + SFML.Graphics.BlendMode.Equation.Add + ); /// - /// Multiply Blend (PremultipliedAlpha Only) + /// Additive Blend with PremultipliedAlpha + /// + /// [res.c * res.a] = [src.c * src.a] * 1 + [dst.c * dst.a] * 1 + /// res.a = src.a * 1 + dst.a * 1 + /// + /// + public static SFML.Graphics.BlendMode AdditivePma = new( + SFML.Graphics.BlendMode.Factor.One, + SFML.Graphics.BlendMode.Factor.One, + SFML.Graphics.BlendMode.Equation.Add, + SFML.Graphics.BlendMode.Factor.One, + SFML.Graphics.BlendMode.Factor.One, + SFML.Graphics.BlendMode.Equation.Add + ); + + /// + /// Multiply Blend with PremultipliedAlpha /// /// res.c = src.c * dst.c + dst.c * (1 - src.a) - /// res.a = src.a * 1 + dst.a * (1 - src.a) + /// res.a = src.a * 1 + dst.a * (1 - src.a) /// /// - public static SFML.Graphics.BlendMode Multiply = new( + public static SFML.Graphics.BlendMode MultiplyPma = new( SFML.Graphics.BlendMode.Factor.DstColor, SFML.Graphics.BlendMode.Factor.OneMinusSrcAlpha, SFML.Graphics.BlendMode.Equation.Add, @@ -46,13 +96,13 @@ namespace SpineViewer.Spine ); /// - /// Screen Blend (PremultipliedAlpha Only) + /// Screen Blend with PremultipliedAlpha Only /// /// res.c = src.c * 1 + dst.c * (1 - src.c) = 1 - [(1 - src.c)(1 - dst.c)] /// res.a = src.a * 1 + dst.a * (1 - src.a) /// /// - public static SFML.Graphics.BlendMode Screen = new( + public static SFML.Graphics.BlendMode ScreenPma = new( SFML.Graphics.BlendMode.Factor.One, SFML.Graphics.BlendMode.Factor.OneMinusSrcColor, SFML.Graphics.BlendMode.Equation.Add, diff --git a/SpineViewer/Spine/Implementations/Spine/Spine21.cs b/SpineViewer/Spine/Implementations/Spine/Spine21.cs index 34ca268..f91c6d4 100644 --- a/SpineViewer/Spine/Implementations/Spine/Spine21.cs +++ b/SpineViewer/Spine/Implementations/Spine/Spine21.cs @@ -261,6 +261,7 @@ namespace SpineViewer.Spine.Implementations.Spine { vertexArray.Clear(); states.Texture = null; + states.Shader = Shader.GetShader(usePremultipliedAlpha); // 要用 DrawOrder 而不是 Slots foreach (var slot in skeleton.DrawOrder) @@ -322,18 +323,13 @@ namespace SpineViewer.Spine.Implementations.Spine } // 似乎 2.1.x 也没有 BlendMode - SFML.Graphics.BlendMode blendMode = slot.Data.AdditiveBlending ? BlendModeSFML.Additive : BlendModeSFML.Normal; + SFML.Graphics.BlendMode blendMode = slot.Data.AdditiveBlending ? BlendModeSFML.AdditivePma : BlendModeSFML.NormalPma; states.Texture ??= texture; if (states.BlendMode != blendMode || states.Texture != texture) { if (vertexArray.VertexCount > 0) { - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; - // 调试纹理 if (!isDebug || debugTexture) target.Draw(vertexArray, states); @@ -377,11 +373,6 @@ namespace SpineViewer.Spine.Implementations.Spine //clipping.ClipEnd(slot); } - - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; //clipping.ClipEnd(); // 调试纹理 diff --git a/SpineViewer/Spine/Implementations/Spine/Spine36.cs b/SpineViewer/Spine/Implementations/Spine/Spine36.cs index b67213c..ddc365a 100644 --- a/SpineViewer/Spine/Implementations/Spine/Spine36.cs +++ b/SpineViewer/Spine/Implementations/Spine/Spine36.cs @@ -208,10 +208,10 @@ namespace SpineViewer.Spine.Implementations.Spine { return spineBlendMode switch { - BlendMode.Normal => BlendModeSFML.Normal, - BlendMode.Additive => BlendModeSFML.Additive, - BlendMode.Multiply => BlendModeSFML.Multiply, - BlendMode.Screen => BlendModeSFML.Screen, + BlendMode.Normal => BlendModeSFML.NormalPma, + BlendMode.Additive => BlendModeSFML.AdditivePma, + BlendMode.Multiply => BlendModeSFML.MultiplyPma, + BlendMode.Screen => BlendModeSFML.ScreenPma, _ => throw new NotImplementedException($"{spineBlendMode}"), }; } @@ -220,6 +220,7 @@ namespace SpineViewer.Spine.Implementations.Spine { vertexArray.Clear(); states.Texture = null; + states.Shader = Shader.GetShader(usePremultipliedAlpha); // 要用 DrawOrder 而不是 Slots foreach (var slot in skeleton.DrawOrder) @@ -286,11 +287,6 @@ namespace SpineViewer.Spine.Implementations.Spine { if (vertexArray.VertexCount > 0) { - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; - // 调试纹理 if (!isDebug || debugTexture) target.Draw(vertexArray, states); @@ -336,11 +332,6 @@ namespace SpineViewer.Spine.Implementations.Spine } clipping.ClipEnd(); - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; - // 调试纹理 if (!isDebug || debugTexture) target.Draw(vertexArray, states); diff --git a/SpineViewer/Spine/Implementations/Spine/Spine37.cs b/SpineViewer/Spine/Implementations/Spine/Spine37.cs index 89a0a00..61d66ce 100644 --- a/SpineViewer/Spine/Implementations/Spine/Spine37.cs +++ b/SpineViewer/Spine/Implementations/Spine/Spine37.cs @@ -178,10 +178,10 @@ namespace SpineViewer.Spine.Implementations.Spine { return spineBlendMode switch { - BlendMode.Normal => BlendModeSFML.Normal, - BlendMode.Additive => BlendModeSFML.Additive, - BlendMode.Multiply => BlendModeSFML.Multiply, - BlendMode.Screen => BlendModeSFML.Screen, + BlendMode.Normal => BlendModeSFML.NormalPma, + BlendMode.Additive => BlendModeSFML.AdditivePma, + BlendMode.Multiply => BlendModeSFML.MultiplyPma, + BlendMode.Screen => BlendModeSFML.ScreenPma, _ => throw new NotImplementedException($"{spineBlendMode}"), }; } @@ -190,6 +190,7 @@ namespace SpineViewer.Spine.Implementations.Spine { vertexArray.Clear(); states.Texture = null; + states.Shader = Shader.GetShader(usePremultipliedAlpha); // 要用 DrawOrder 而不是 Slots foreach (var slot in skeleton.DrawOrder) @@ -256,12 +257,6 @@ namespace SpineViewer.Spine.Implementations.Spine { if (vertexArray.VertexCount > 0) { - // XXX: 实测不用设置 sampler2D 的值也正确 - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; - // 调试纹理 if (!isDebug || debugTexture) target.Draw(vertexArray, states); @@ -307,11 +302,6 @@ namespace SpineViewer.Spine.Implementations.Spine } clipping.ClipEnd(); - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; - // 调试纹理 if (!isDebug || debugTexture) target.Draw(vertexArray, states); diff --git a/SpineViewer/Spine/Implementations/Spine/Spine38.cs b/SpineViewer/Spine/Implementations/Spine/Spine38.cs index 76953ff..b8f2073 100644 --- a/SpineViewer/Spine/Implementations/Spine/Spine38.cs +++ b/SpineViewer/Spine/Implementations/Spine/Spine38.cs @@ -184,10 +184,10 @@ namespace SpineViewer.Spine.Implementations.Spine { return spineBlendMode switch { - BlendMode.Normal => BlendModeSFML.Normal, - BlendMode.Additive => BlendModeSFML.Additive, - BlendMode.Multiply => BlendModeSFML.Multiply, - BlendMode.Screen => BlendModeSFML.Screen, + BlendMode.Normal => BlendModeSFML.NormalPma, + BlendMode.Additive => BlendModeSFML.AdditivePma, + BlendMode.Multiply => BlendModeSFML.MultiplyPma, + BlendMode.Screen => BlendModeSFML.ScreenPma, _ => throw new NotImplementedException($"{spineBlendMode}"), }; } @@ -196,6 +196,7 @@ namespace SpineViewer.Spine.Implementations.Spine { vertexArray.Clear(); states.Texture = null; + states.Shader = Shader.GetShader(usePremultipliedAlpha); // 要用 DrawOrder 而不是 Slots foreach (var slot in skeleton.DrawOrder) @@ -262,14 +263,8 @@ namespace SpineViewer.Spine.Implementations.Spine { if (vertexArray.VertexCount > 0) { - // XXX: 实测不用设置 sampler2D 的值也正确 - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; - // 调试纹理 - if (!isDebug || debugTexture) + if (!isDebug || debugTexture) target.Draw(vertexArray, states); vertexArray.Clear(); @@ -313,11 +308,6 @@ namespace SpineViewer.Spine.Implementations.Spine } clipping.ClipEnd(); - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; - // 调试纹理 if (!isDebug || debugTexture) target.Draw(vertexArray, states); diff --git a/SpineViewer/Spine/Implementations/Spine/Spine40.cs b/SpineViewer/Spine/Implementations/Spine/Spine40.cs index 528e58a..b6ec861 100644 --- a/SpineViewer/Spine/Implementations/Spine/Spine40.cs +++ b/SpineViewer/Spine/Implementations/Spine/Spine40.cs @@ -180,10 +180,10 @@ namespace SpineViewer.Spine.Implementations.Spine { return spineBlendMode switch { - BlendMode.Normal => BlendModeSFML.Normal, - BlendMode.Additive => BlendModeSFML.Additive, - BlendMode.Multiply => BlendModeSFML.Multiply, - BlendMode.Screen => BlendModeSFML.Screen, + BlendMode.Normal => BlendModeSFML.NormalPma, + BlendMode.Additive => BlendModeSFML.AdditivePma, + BlendMode.Multiply => BlendModeSFML.MultiplyPma, + BlendMode.Screen => BlendModeSFML.ScreenPma, _ => throw new NotImplementedException($"{spineBlendMode}"), }; } @@ -192,6 +192,7 @@ namespace SpineViewer.Spine.Implementations.Spine { vertexArray.Clear(); states.Texture = null; + states.Shader = Shader.GetShader(usePremultipliedAlpha); // 要用 DrawOrder 而不是 Slots foreach (var slot in skeleton.DrawOrder) @@ -258,12 +259,6 @@ namespace SpineViewer.Spine.Implementations.Spine { if (vertexArray.VertexCount > 0) { - // XXX: 实测不用设置 sampler2D 的值也正确 - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; - // 调试纹理 if (!isDebug || debugTexture) target.Draw(vertexArray, states); @@ -309,11 +304,6 @@ namespace SpineViewer.Spine.Implementations.Spine } clipping.ClipEnd(); - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; - // 调试纹理 if (!isDebug || debugTexture) target.Draw(vertexArray, states); diff --git a/SpineViewer/Spine/Implementations/Spine/Spine41.cs b/SpineViewer/Spine/Implementations/Spine/Spine41.cs index f995319..3471db1 100644 --- a/SpineViewer/Spine/Implementations/Spine/Spine41.cs +++ b/SpineViewer/Spine/Implementations/Spine/Spine41.cs @@ -180,10 +180,10 @@ namespace SpineViewer.Spine.Implementations.Spine { return spineBlendMode switch { - BlendMode.Normal => BlendModeSFML.Normal, - BlendMode.Additive => BlendModeSFML.Additive, - BlendMode.Multiply => BlendModeSFML.Multiply, - BlendMode.Screen => BlendModeSFML.Screen, + BlendMode.Normal => BlendModeSFML.NormalPma, + BlendMode.Additive => BlendModeSFML.AdditivePma, + BlendMode.Multiply => BlendModeSFML.MultiplyPma, + BlendMode.Screen => BlendModeSFML.ScreenPma, _ => throw new NotImplementedException($"{spineBlendMode}"), }; } @@ -192,6 +192,7 @@ namespace SpineViewer.Spine.Implementations.Spine { vertexArray.Clear(); states.Texture = null; + states.Shader = Shader.GetShader(usePremultipliedAlpha); // 要用 DrawOrder 而不是 Slots foreach (var slot in skeleton.DrawOrder) @@ -258,12 +259,6 @@ namespace SpineViewer.Spine.Implementations.Spine { if (vertexArray.VertexCount > 0) { - // XXX: 实测不用设置 sampler2D 的值也正确 - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; - // 调试纹理 if (!isDebug || debugTexture) target.Draw(vertexArray, states); @@ -309,11 +304,6 @@ namespace SpineViewer.Spine.Implementations.Spine } clipping.ClipEnd(); - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; - // 调试纹理 if (!isDebug || debugTexture) target.Draw(vertexArray, states); diff --git a/SpineViewer/Spine/Implementations/Spine/Spine42.cs b/SpineViewer/Spine/Implementations/Spine/Spine42.cs index d6fc73e..1697385 100644 --- a/SpineViewer/Spine/Implementations/Spine/Spine42.cs +++ b/SpineViewer/Spine/Implementations/Spine/Spine42.cs @@ -180,10 +180,10 @@ namespace SpineViewer.Spine.Implementations.Spine { return spineBlendMode switch { - BlendMode.Normal => BlendModeSFML.Normal, - BlendMode.Additive => BlendModeSFML.Additive, - BlendMode.Multiply => BlendModeSFML.Multiply, - BlendMode.Screen => BlendModeSFML.Screen, + BlendMode.Normal => BlendModeSFML.NormalPma, + BlendMode.Additive => BlendModeSFML.AdditivePma, + BlendMode.Multiply => BlendModeSFML.MultiplyPma, + BlendMode.Screen => BlendModeSFML.ScreenPma, _ => throw new NotImplementedException($"{spineBlendMode}"), }; } @@ -192,6 +192,7 @@ namespace SpineViewer.Spine.Implementations.Spine { vertexArray.Clear(); states.Texture = null; + states.Shader = Shader.GetShader(usePremultipliedAlpha); // 要用 DrawOrder 而不是 Slots foreach (var slot in skeleton.DrawOrder) @@ -258,12 +259,6 @@ namespace SpineViewer.Spine.Implementations.Spine { if (vertexArray.VertexCount > 0) { - // XXX: 实测不用设置 sampler2D 的值也正确 - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; - // 调试纹理 if (!isDebug || debugTexture) target.Draw(vertexArray, states); @@ -309,11 +304,6 @@ namespace SpineViewer.Spine.Implementations.Spine } clipping.ClipEnd(); - if (usePremultipliedAlpha && (states.BlendMode == BlendModeSFML.Normal || states.BlendMode == BlendModeSFML.Additive)) - states.Shader = Shader.FragmentShader; - else - states.Shader = null; - // 调试纹理 if (!isDebug || debugTexture) target.Draw(vertexArray, states); diff --git a/SpineViewer/Spine/Shader.cs b/SpineViewer/Spine/Shader.cs index fd3f206..a2b2ded 100644 --- a/SpineViewer/Spine/Shader.cs +++ b/SpineViewer/Spine/Shader.cs @@ -9,19 +9,44 @@ namespace SpineViewer.Spine public static class Shader { /// - /// 用于解决 PMA 和渐变动画问题的片段着色器 + /// 用于非预乘纹理的 fragment shader, 乘上了插值后的透明度用于实现透明度变化(插值预乘), 并且输出预乘后的像素值 /// - private const string FRAGMENT_SHADER = ( + private const string FRAGMENT_VertexAlpha = ( "uniform sampler2D t;" + - "void main() { vec4 p = texture2D(t, gl_TexCoord[0].xy);" + - "if (p.a > 0) p.rgb /= max(max(max(p.r, p.g), p.b), p.a);" + + "void main() { vec4 p = texture(t, gl_TexCoord[0].xy);" + + "p.rgb *= p.a * gl_Color.a;" + "gl_FragColor = gl_Color * p; }" ); /// - /// 针对预乘 Alpha 通道的片段着色器 + /// 用于预乘纹理的 fragment shader, 乘上了插值后的透明度用于实现透明度变化(插值预乘) /// - public static SFML.Graphics.Shader? FragmentShader { get; private set; } + private const string FRAGMENT_VertexAlphaPma = ( + "uniform sampler2D t;" + + "void main() { vec4 p = texture(t, gl_TexCoord[0].xy);" + + "p.rgb *= gl_Color.a;" + + "gl_FragColor = gl_Color * p; }" + ); + + /// + /// 预乘转非预乘 fragment shader + /// + private const string FRAGMENT_PmaInv = ( + "uniform sampler2D t;" + + "void main() { vec4 p = texture(t, gl_TexCoord[0].xy);" + + "p.rgb *= gl_Color.a;" + + "gl_FragColor = gl_Color * p; }" + ); + + /// + /// 考虑了顶点透明度变化的着色器, 输入是非预乘纹理像素, 输出是预乘像素 + /// + private static SFML.Graphics.Shader? VertexAlpha = null; + + /// + /// 考虑了顶点透明度变化的着色器, 输入和输出均是预乘像素值 + /// + private static SFML.Graphics.Shader? VertexAlphaPma = null; /// /// 加载 Shader, 可能会存在异常导致着色器加载失败 @@ -29,7 +54,21 @@ namespace SpineViewer.Spine /// public static void Init() { - FragmentShader = SFML.Graphics.Shader.FromString(null, null, FRAGMENT_SHADER); + VertexAlpha = SFML.Graphics.Shader.FromString(null, null, FRAGMENT_VertexAlpha); + VertexAlphaPma = SFML.Graphics.Shader.FromString(null, null, FRAGMENT_VertexAlphaPma); + } + + /// + /// 获取合适的着色器 + /// + /// 纹理是否是预乘的 + /// 是否是双色着色的(TODO) + public static SFML.Graphics.Shader? GetShader(bool pma, bool twoColor = false) + { + if (pma) + return VertexAlphaPma; + else + return VertexAlpha; } } }