float alphaOver(float baseAlpha, float overAlpha) { return overAlpha + baseAlpha * (1.0 - overAlpha); } float4 compositeOver(float4 baseColor, float4 overColor) { float outAlpha = alphaOver(baseColor.a, overColor.a); float3 outRgb = overColor.rgb + baseColor.rgb * (1.0 - overColor.a); return float4(outRgb, outAlpha); } float sdfCoverage(float2 uv, float edge, float aa) { float distance = sampleTitleText(uv); return smoothstep(edge - aa, edge + aa, distance); } float4 shadeVideo(ShaderContext context) { float2 resolution = max(context.outputResolution, float2(1.0, 1.0)); float aspect = resolution.x / resolution.y; float2 textSize = float2(0.72 * scale, 0.09 * scale * aspect); float2 safeTextSize = max(textSize, float2(0.0001, 0.0001)); float2 textUv = (context.uv - position) / safeTextSize; bool insideTextRect = textUv.x >= 0.0 && textUv.x <= 1.0 && textUv.y >= 0.0 && textUv.y <= 1.0; float distance = insideTextRect ? sampleTitleText(textUv) : 0.0; float edge = 0.5; float aa = max(fwidth(distance) * (1.75 + softness * 5.0), 0.0025); float2 pixelTextUv = (1.0 / resolution) / safeTextSize; float2 sampleOffset = pixelTextUv * 0.38; float fill = ( sdfCoverage(textUv, edge, aa) * 2.0 + sdfCoverage(textUv + float2(sampleOffset.x, sampleOffset.y), edge, aa) + sdfCoverage(textUv + float2(-sampleOffset.x, sampleOffset.y), edge, aa) + sdfCoverage(textUv + float2(sampleOffset.x, -sampleOffset.y), edge, aa) + sdfCoverage(textUv + float2(-sampleOffset.x, -sampleOffset.y), edge, aa)) / 6.0; float outlineDistance = outlineWidth * 0.16; float outlineEdge = edge - outlineDistance; float outline = ( sdfCoverage(textUv, outlineEdge, aa) * 2.0 + sdfCoverage(textUv + float2(sampleOffset.x, sampleOffset.y), outlineEdge, aa) + sdfCoverage(textUv + float2(-sampleOffset.x, sampleOffset.y), outlineEdge, aa) + sdfCoverage(textUv + float2(sampleOffset.x, -sampleOffset.y), outlineEdge, aa) + sdfCoverage(textUv + float2(-sampleOffset.x, -sampleOffset.y), outlineEdge, aa)) / 6.0; float outlineAlpha = saturate(outline - fill) * outlineColor.a; float fillAlpha = fill * fillColor.a; float textAlpha = max(fillAlpha, outlineAlpha); if (textAlpha <= 0.0001) return context.sourceColor; float4 base = context.sourceColor; float4 outlineLayer = float4(outlineColor.rgb * outlineAlpha, outlineAlpha); float4 fillLayer = float4(fillColor.rgb * fillAlpha, fillAlpha); return saturate(compositeOver(compositeOver(base, outlineLayer), fillLayer)); }