feat(blur): the brand logo cannot be blurred

The blur is universal, so it would swallow the logo along with everything else. The compositor
now defers every visible brand logo: skipped in both element loops, blitted immediately AFTER
the blur group, before the flash/social/ticker overlays. One logo per scene, so it is cheap.

Preview mirrors it: the staged scene's brand logo is drawn above the blur host (StagedBrandLogo),
so what you see in the editor is what the encoder gets.

Test: a blur covering the logo's area leaves the logo's pixels exactly white while the coloured
background beneath it blends.
This commit is contained in:
2026-11-01 13:32:23 -08:00
parent bb51164f2f
commit 9b337ad91b
5 changed files with 115 additions and 0 deletions
+15
View File
@@ -187,6 +187,9 @@ public sealed class SceneCompositor
case Source { IsBackground: true }:
case Source { Type: SourceType.Background }:
case Source { Type: SourceType.TextOverlay }:
// ⛔ The brand logo is drawn AFTER the blur group (creator ruling 2026-11-01):
// the blur is universal and must never hide the brand.
case Source { IsBrandLogo: true }:
case ZoomSceneElement { IsZoomActive: true }:
continue;
}
@@ -201,6 +204,15 @@ public sealed class SceneCompositor
// overlapping blurs still resolve to the strongest single one.
ApplyBlurLayers(scene, buffer, cropW, cropH, options, timings);
// ⛔ The brand logo cannot be blurred (creator ruling 2026-11-01): it is blitted after the
// universal blur, so a privacy cover never swallows it. One per scene, so this is cheap.
foreach (var brand in scene.Elements.OfType<Source>().Where(s => s.IsBrandLogo && s.IsVisible))
{
var brandFrame = frameFor(brand);
if (brandFrame == null) continue;
BlitBakedElement(buffer, cropW, cropH, options, brand, brandFrame, timings, $"brand {brand.Name}");
}
if (flashFrame != null)
{
var tFlash = System.Diagnostics.Stopwatch.GetTimestamp();
@@ -358,6 +370,9 @@ public sealed class SceneCompositor
case Source { IsBackground: true }:
case Source { Type: SourceType.Background }:
case Source { Type: SourceType.TextOverlay }:
// ⛔ The brand logo is drawn AFTER the blur group (creator ruling 2026-11-01):
// the blur is universal and must never hide the brand.
case Source { IsBrandLogo: true }:
case ZoomSceneElement { IsZoomActive: true }:
continue;
}