Advanced Visuals: Partitioning & Filters
Two Gameface-specific rendering features unlock visual and performance capabilities that standard browser CSS cannot match. Backdrop filters blur or invert the live 3D scene behind a UI panel, not a static screenshot. UI Surface Partitioning renders each HUD component into its own texture, replacing a single full-resolution UI texture with several small ones. Both features involve cooperation between the frontend and the engine integration team.
Backdrop Filter
Section titled “Backdrop Filter”The CSS backdrop-filter property lets an element apply filter effects (blur, invert, brightness, contrast) to whatever is rendered behind it. In a standard browser, “behind” means other DOM elements. In Gameface, “behind” can include the live 3D game scene, which is what makes this feature notable.
The CSS is standard:
import Block from '@components/Layout/Block/Block';import TextBlock from '@components/Basic/TextBlock/TextBlock';
const HudPanel = () => ( <Block class="hud-panel"> <TextBlock class="hud-panel__title">Mission Briefing</TextBlock> <TextBlock>Proceed to extraction point Alpha.</TextBlock> </Block>);<div class="hud-panel"> <h2>Mission Briefing</h2> <p>Proceed to extraction point Alpha.</p></div>.hud-panel { background-color: rgba(10, 10, 20, 0.4); /* semi-transparent so blur is visible */ backdrop-filter: blur(8px); border: 1px solid rgba(255, 255, 255, 0.15); padding: 1.5rem 2rem; border-radius: 6px;}When the engine integration provides the current frame’s rendered scene as the background texture, the blur samples from the actual 3D content directly behind the panel, not a flat color.
The Backdrop Root Image
Section titled “The Backdrop Root Image”backdrop-filter does not blur everything behind an element. It blurs only the content within the current Backdrop Root Image, which is the section of the DOM that Gameface considers “the background” at the point where the filter is applied.
A new Backdrop Root Image starts whenever any ancestor element has one of these CSS properties active:
filter(any value other thannone)opacityless than1.0mask,mask-image, orclip-path(any value other thannone)backdrop-filter(any value other thannone)mix-blend-mode(any value other thannormal)coh-composition-id(any value)
Think of these as barriers. Content on the other side of a barrier is excluded from what the filter sees.
This example shows the practical consequence:
import Block from '@components/Layout/Block/Block';
const DimmedWrapper = () => ( <Block class="dimmed-wrapper"> <Block class="blurred-overlay" /> </Block>);<!-- Outer element with opacity: its children form a new Backdrop Root Image --><div class="dimmed-wrapper" style="opacity: 0.8;"> <div class="card card--blue"></div> <div class="card card--green"></div>
<!-- This blurs only the two cards above, NOT the page background --> <div class="panel-overlay"> Blurs the cards, not the 3D scene behind the whole page </div></div>.dimmed-wrapper { opacity: 0.8; /* creates a new Backdrop Root Image here */}
.panel-overlay { backdrop-filter: blur(6px); background-color: rgba(0, 0, 0, 0.3);}The opacity: 0.8 on .dimmed-wrapper acts as the barrier. The blur on .panel-overlay sees only the two card siblings, not the body background or the 3D scene. If you remove the opacity from the wrapper, the blur reaches back to the root element (the <body>), which includes the 3D scene if the engine has provided it.
Blurring the 3D Scene
Section titled “Blurring the 3D Scene”For backdrop-filter to reach the actual 3D scene (not just other DOM elements), the engine integration must supply the current frame’s rendered scene as a “user-defined background” texture to Gameface before rendering begins. This texture is passed through a call on the Gameface View object each frame.
The engine team on your project handles this wiring. From the frontend side, the only requirements are:
- The element using
backdrop-filtermust have the root<body>element as part of its Backdrop Root Image, which means no opacity, filter, or mask properties on any ancestor between the<body>and the filtered element. coh-composition-idon any ancestor also creates a boundary that excludes the scene.
If the engine team has not yet provided the user background texture, backdrop-filter will still apply to whatever DOM elements are behind the filtered element. The 3D content simply will not be included.
Available Filter Functions
Section titled “Available Filter Functions”backdrop-filter supports the same functions as filter:
.panel-frosted { backdrop-filter: blur(10px);}
.panel-dark-glass { backdrop-filter: blur(6px) brightness(0.7);}
.panel-inverted { backdrop-filter: invert(1);}
.panel-saturated { backdrop-filter: saturate(2) blur(4px);}Multiple functions can be chained. They execute left-to-right on the same backdrop image.
Performance Implications
Section titled “Performance Implications”Elements with backdrop-filter are redrawn every frame, regardless of whether the element itself has changed. This is by design: the scene behind the UI is assumed to change every frame, so Gameface cannot cache the filtered result.
This means the cost of each backdrop-filter element scales with the number of active backdrop filters in the DOM, not just whether content changed. A single blurred panel behind a HUD has an acceptable cost. Ten blurred panels on the same frame each re-sample and filter the backdrop separately.
Practical rules:
- Limit
backdrop-filterto elements that are genuinely large or contextually important. Icon overlays, tooltips, and minor decorative elements are not worth the per-frame cost. - Avoid animating
backdrop-filtervalues (changing the blur radius in a loop). The value change forces the filter to re-execute each frame at full cost regardless of caching. - Where the frosted glass look is needed for performance-sensitive screens, consider faking it with a semi-transparent background and a static inner shadow instead of a live blur.
UI Surface Partitioning
Section titled “UI Surface Partitioning”Standard Gameface rendering writes the entire UI to a single full-resolution texture equal in size to the view. At 4K (3840 × 2160), that texture is always fully allocated even when the actual UI content only occupies the corners of the screen.
UI Surface Partitioning resolves this by rendering each top-level UI component into its own individual texture. A minimap in the bottom-left corner gets its own small texture. The health bar in the top-left gets another. The engine composites these textures at their correct screen positions using its own rendering pipeline, and no single full-resolution UI texture is ever created.
The memory saving is significant: four 400×300 corner panels replace one 3840×2160 texture. The math is roughly 30x less texture memory for that UI.
When to Use It
Section titled “When to Use It”Surface partitioning is the right tool when:
- The UI is a HUD with discrete, spatially separated components (minimap, health bar, inventory slots, objective tracker).
- Most of the screen area contains no UI elements.
- The game runs at 4K or other high resolutions where the full-resolution UI texture cost is measurable.
It is the wrong tool when:
- The UI covers most of the screen (full-screen menus, inventory screens, character creation).
- UI elements overlap each other in complex ways.
- The UI uses
backdrop-filterextensively (partitioned elements create Backdrop Root Image boundaries that exclude scene content from filters).
Marking Elements for Partitioning
Section titled “Marking Elements for Partitioning”The entire frontend change is adding two CSS properties to your top-level HUD elements.
coh-partitioned: on tells Gameface to render this element into its own texture. coh-composition-id assigns a string identifier the engine uses to map the rendered texture back to its screen position and visibility state.
import Block from '@components/Layout/Block/Block';
const HudRoot = () => ( <> <Block class="hud-minimap" attr:coh-partitioned="on" attr:coh-composition-id="minimap-surface" /> <Block class="hud-health-bar" attr:coh-partitioned="on" attr:coh-composition-id="health-surface" /> </>);<body> <div class="hud-minimap" style="coh-partitioned: on; coh-composition-id: minimap;"> <!-- minimap content --> </div>
<div class="hud-healthbar" style="coh-partitioned: on; coh-composition-id: healthbar;"> <!-- health bar content --> </div>
<div class="hud-objectives" style="coh-partitioned: on; coh-composition-id: objectives;"> <!-- objectives list --> </div>
<div class="hud-ammo" style="coh-partitioned: on; coh-composition-id: ammo;"> <!-- ammo counter --> </div></body>In practice, apply these properties via a stylesheet class rather than inline styles to keep the HTML clean:
.hud-minimap { position: fixed; bottom: 2rem; left: 2rem; width: 280px; height: 280px; coh-partitioned: on; coh-composition-id: minimap;}
.hud-healthbar { position: fixed; bottom: 2rem; right: 2rem; width: 320px; height: 80px; coh-partitioned: on; coh-composition-id: healthbar;}
.hud-objectives { position: fixed; top: 2rem; right: 2rem; width: 300px; height: auto; coh-partitioned: on; coh-composition-id: objectives;}
.hud-ammo { position: fixed; bottom: 6rem; right: 2rem; width: 200px; height: 60px; coh-partitioned: on; coh-composition-id: ammo;}Constraints You Must Know
Section titled “Constraints You Must Know”Top-level only. coh-partitioned: on only works on direct children of <body>. Applying it to a nested element (a child of a child) will result in the element not rendering and a warning in the console. Every partitioned element must be a first-level descendant of <body>.
All or nothing. When the engine initializes the view with surface partitioning enabled, every top-level DOM element must be marked with coh-partitioned: on. If any top-level element is left unmarked, its rendering will be incorrect. The two supported configurations are: partitioning enabled with all top-level elements marked, or partitioning disabled with no elements marked. Mixing is not supported.
No draw-order management. Gameface does not inform the engine about the z-index of partitioned elements. If two partitioned panels need to render in a specific depth order (one visually above the other), the engine integration team must handle that ordering explicitly in the compositor. Do not rely on CSS z-index between partitioned siblings to produce correct overlap in the final composited image.
coh-composition-id creates a Backdrop Root Image boundary. Partitioned elements cannot use backdrop-filter to blur the 3D scene through their partition boundary. The scene-blur use case and surface partitioning are mutually exclusive at the element level.
© 2026 Coherent Labs. All rights reserved.