UnityVersion:2021.3.0f1
UrpVersion:12.1.6
ColorSpace:Linear
SpineRuntimeVersion: 4.0.0+
问题:
动画资源文件有一个关于color alpha的关键帧,我们在导入Unity之后,发现在UGUI下SkeletonGraphic显示的效果有问题。(与之相比,它在Unity2D中的SkeletonAnimation更接近我们想要的真实效果)
特效背后的紫色背光(slot名为E3D-Point134),在slot 透明度接近0.1的时候会出现闪烁的现象,即输入的alpha值更低,反而紫色背光更亮。对比图如下:
尝试解决:
经过查阅代码,发现可能问题是在Spine-SkeletonGraphic-NormalPass.cginc的顶点着色器中
VertexOutput vert (VertexInput IN) {
VertexOutput OUT;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.worldPosition = IN.vertex;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
OUT.texcoord = IN.texcoord;
#ifdef UNITY_HALF_TEXEL_OFFSET
OUT.vertex.xy += (_ScreenParams.zw-1.0) * float2(-1,1);
#endif
#ifdef _CANVAS_GROUP_COMPATIBLE
half4 vertexColor = IN.color;
// CanvasGroup alpha sets vertex color alpha, but does not premultiply it to rgb components.
vertexColor.rgb *= vertexColor.a;
// Unfortunately we cannot perform the TargetToGamma and PMAGammaToTarget transformations,
// as these would be wrong with modified alpha.
#else
// Note: CanvasRenderer performs a GammaToTargetSpace conversion on vertex color already,
// however incorrectly assuming straight alpha color.
float4 vertexColor = PMAGammaToTargetSpace(half4(TargetToGammaSpace(IN.color.rgb), IN.color.a));
#endif
OUT.color = vertexColor * float4(_Color.rgb * _Color.a, _Color.a); // Combine a PMA version of _Color with vertexColor.
return OUT;
}
VertexOutput OUT;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.worldPosition = IN.vertex;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
OUT.texcoord = IN.texcoord;
#ifdef UNITY_HALF_TEXEL_OFFSET
OUT.vertex.xy += (_ScreenParams.zw-1.0) * float2(-1,1);
#endif
#ifdef _CANVAS_GROUP_COMPATIBLE
half4 vertexColor = IN.color;
// CanvasGroup alpha sets vertex color alpha, but does not premultiply it to rgb components.
vertexColor.rgb *= vertexColor.a;
// Unfortunately we cannot perform the TargetToGamma and PMAGammaToTarget transformations,
// as these would be wrong with modified alpha.
#else
// Note: CanvasRenderer performs a GammaToTargetSpace conversion on vertex color already,
// however incorrectly assuming straight alpha color.
float4 vertexColor = PMAGammaToTargetSpace(half4(TargetToGammaSpace(IN.color.rgb), IN.color.a));
#endif
OUT.color = vertexColor * float4(_Color.rgb * _Color.a, _Color.a); // Combine a PMA version of _Color with vertexColor.
return OUT;
}
float4 vertexColor = PMAGammaToTargetSpace(half4(TargetToGammaSpace(IN.color.rgb), IN.color.a));
可能的问题:我们猜想是这两次颜色空间的转换可能在IN.color.a小于0.12(大致范围)的时候,发生了一些问题,导致alpha越小,最后输出的颜色反而越亮。但是通过代码并没有发现具体的问题所在。因此我们尝试在这里做一些强制的限制,发现闪烁的情况消失了。
float4 vertexColor = PMAGammaToTargetSpace(half4(TargetToGammaSpace(IN.color.rgb), IN.color.a));
if(IN.color.a<=0.12){
vertexColor = IN.color;
}
当然代价是,alpha小于0.12的时候,颜色的转换是有问题的。这也是不正确的。if(IN.color.a<=0.12){
vertexColor = IN.color;
}
求助:
请问这个问题是否是因为本身这个转换算法会带来精度问题?还是因为我们忽略了某些设置?以下是SkeletonGraphic以及资产中SkeletonData的设置
希望您可以下载这里的动画资产文件,您会发现动画末尾的紫色背光会有闪烁现象。如果不太明显,可以将动画速率调整至原来的0.3倍左右,这样能够比较清晰地看到这个问题。
动画资产文件:
不胜感激!