@@ -34,11 +34,45 @@ std::optional<Entity> MatrixFilterContents::RenderFilter(
3434 return std::nullopt ;
3535 }
3636
37- auto & transform = is_subpass_ ? effect_transform : entity.GetTransformation ();
38- snapshot->transform = snapshot->transform * //
39- transform * //
40- matrix_ * //
41- transform.Invert ();
37+ if (is_subpass_) {
38+ // There are two special quirks with how Matrix filters behave when used as
39+ // subpass backdrop filters:
40+ //
41+ // 1. For subpass backdrop filters, the snapshot transform is always just a
42+ // translation that positions the parent pass texture correctly relative
43+ // to the subpass texture. However, this translation always needs to be
44+ // applied in screen space.
45+ //
46+ // Since we know the snapshot transform will always have an identity
47+ // basis in this case, we safely reverse the order and apply the filter's
48+ // matrix within the snapshot transform space.
49+ //
50+ // 2. The filter's matrix needs to be applied within the space defined by
51+ // the scene's current transformation matrix (CTM). For example: If the
52+ // CTM is scaled up, then translations applied by the matrix should be
53+ // magnified accordingly.
54+ //
55+ // To accomplish this, we sandwitch the filter's matrix within the CTM in
56+ // both cases. But notice that for the subpass backdrop filter case, we
57+ // use the "effect transform" instead of the Entity's transform!
58+ //
59+ // That's because in the subpass backdrop filter case, the Entity's
60+ // transform isn't actually the captured CTM of the scene like it usually
61+ // is; instead, it's just a screen space translation that offsets the
62+ // backdrop texture (as mentioned above). And so we sneak the subpass's
63+ // captured CTM in through the effect transform.
64+ //
65+
66+ snapshot->transform = snapshot->transform * //
67+ effect_transform * //
68+ matrix_ * //
69+ effect_transform.Invert ();
70+ } else {
71+ snapshot->transform = entity.GetTransformation () * //
72+ matrix_ * //
73+ entity.GetTransformation ().Invert () * //
74+ snapshot->transform ;
75+ }
4276 snapshot->sampler_descriptor = sampler_descriptor_;
4377 return Entity::FromSnapshot (snapshot, entity.GetBlendMode (),
4478 entity.GetStencilDepth ());
0 commit comments