Annotations
This commit is contained in:
@@ -23,6 +23,8 @@ float3 matteSampleColor(float2 uv, ShaderContext context)
|
||||
if (blur <= 0.0001)
|
||||
return center;
|
||||
|
||||
// Pre-blur only the color used for screen comparison; the final image keeps
|
||||
// its original detail and alpha is refined in a later pass.
|
||||
float2 radius = pixel * blur;
|
||||
float3 color = center * 0.36;
|
||||
color += saturate(sampleVideo(saturate(uv + float2(radius.x, 0.0))).rgb) * 0.16;
|
||||
@@ -37,6 +39,8 @@ float keyDistanceAt(float2 uv, ShaderContext context)
|
||||
float3 color = matteSampleColor(uv, context);
|
||||
float3 keyColor = saturate(screenColor.rgb);
|
||||
float chromaDistance = distance(chroma709(color), chroma709(keyColor)) * 2.65;
|
||||
// Direction distance is less sensitive to brightness, while chroma distance
|
||||
// follows broadcast-style color difference; screenBalance blends the two.
|
||||
float directionDistance = length(safeNormalize(max(color, float3(0.0001, 0.0001, 0.0001))) - safeNormalize(max(keyColor, float3(0.0001, 0.0001, 0.0001)))) * 0.55;
|
||||
return lerp(directionDistance, chromaDistance, saturate(screenBalance));
|
||||
}
|
||||
@@ -65,6 +69,8 @@ float refinedAlphaFromMatte(float2 uv, ShaderContext context)
|
||||
|
||||
if (aaRadius > 0.0001)
|
||||
{
|
||||
// A small fixed kernel smooths edges and collects min/max alpha for
|
||||
// black/white cleanup without needing dynamic loops or arrays.
|
||||
float2 radius = pixel * aaRadius;
|
||||
float2 halfRadius = radius * 0.5;
|
||||
float alphaMin = centerAlpha;
|
||||
@@ -126,6 +132,8 @@ float refinedAlphaFromMatte(float2 uv, ShaderContext context)
|
||||
alpha = centerAlpha;
|
||||
}
|
||||
|
||||
// Final matte shaping happens after blur/cleanup so clip and contrast affect
|
||||
// the refined edge rather than the raw screen-distance estimate.
|
||||
alpha = saturate((alpha - clipBlack) / max(clipWhite - clipBlack, 0.0001));
|
||||
alpha = saturate((alpha - 0.5) * max(matteContrast, 0.0001) + 0.5);
|
||||
alpha = pow(max(alpha, 0.0), max(matteGamma, 0.0001));
|
||||
@@ -135,6 +143,8 @@ float refinedAlphaFromMatte(float2 uv, ShaderContext context)
|
||||
float spillAmountForColor(float3 color)
|
||||
{
|
||||
float3 keyColor = saturate(screenColor.rgb);
|
||||
// Measure spill as color energy aligned with the screen color minus the
|
||||
// strongest opposing channel, leaving neutral highlights mostly intact.
|
||||
float keyComponent = dot(color, safeNormalize(max(keyColor, float3(0.0001, 0.0001, 0.0001))));
|
||||
float opposingComponent = max(max(color.r * (1.0 - keyColor.r), color.g * (1.0 - keyColor.g)), color.b * (1.0 - keyColor.b));
|
||||
return saturate(keyComponent - opposingComponent + despillBias);
|
||||
@@ -187,6 +197,8 @@ float4 applyKey(ShaderContext context)
|
||||
float cropMask = cropMaskAt(context.uv, context);
|
||||
alpha *= cropMask;
|
||||
|
||||
// Edge recovery is strongest around 50% alpha, where fringing usually lives,
|
||||
// and fades away for solid foreground/background pixels.
|
||||
float edgeAmount = saturate(1.0 - abs(alpha * 2.0 - 1.0));
|
||||
despilled = lerp(despilled, despilled * saturate(edgeColor.rgb), edgeAmount * saturate(edgeRecover));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user