diff --git a/src/SharpEmu.Libs/Agc/AgcExports.cs b/src/SharpEmu.Libs/Agc/AgcExports.cs index 368facd..420a274 100644 --- a/src/SharpEmu.Libs/Agc/AgcExports.cs +++ b/src/SharpEmu.Libs/Agc/AgcExports.cs @@ -3296,10 +3296,60 @@ public static class AgcExports globalMemoryBindings, vertexInputs, renderTargets, - CreateRenderState(state.CxRegisters, renderTargets.FirstOrDefault())); + ApplyTransparentPremultipliedFillClear( + CreateRenderState(state.CxRegisters, renderTargets.FirstOrDefault()), + textures, + vertexInputs, + pixelEvaluation.InitialScalarRegisters)); return true; } + private static readonly bool _transparentFillClearEnabled = !string.Equals( + Environment.GetEnvironmentVariable("SHARPEMU_DISABLE_TRANSPARENT_FILL_CLEAR"), + "1", + StringComparison.Ordinal); + + /// + /// Chowdren resets its effect layers with an untextured transparent-black + /// fill using premultiplied blending. With One/OneMinusSrcAlpha that draw + /// is otherwise a no-op, causing fog and vignette layers to accumulate. + /// Treat precisely that draw shape as an overwrite. + /// + private static VulkanGuestRenderState ApplyTransparentPremultipliedFillClear( + VulkanGuestRenderState renderState, + IReadOnlyList textures, + IReadOnlyList vertexInputs, + IReadOnlyList pixelUserData) + { + if (!_transparentFillClearEnabled || + textures.Count != 0 || + vertexInputs.Count != 0 || + pixelUserData.Count < 4 || + renderState.Blend is not + { + Enable: true, + ColorSrcFactor: 1, + ColorDstFactor: 5, + ColorFunc: 0, + }) + { + return renderState; + } + + for (var index = 0; index < 4; index++) + { + if ((pixelUserData[index] & 0x7FFF_FFFFu) != 0) + { + return renderState; + } + } + + return renderState with + { + Blend = renderState.Blend with { Enable = false }, + }; + } + private static VulkanGuestIndexBuffer? CreateVulkanIndexBuffer( CpuContext ctx, SubmittedDcbState state,