Skip to content
SiteEmail

API

Deprecated the linear rendering pipeline and removed automatic mode selection based on the render target. Rendering now defaults to the gamma pipeline with the sRGB color space and gamma blending, and users should migrate to gamma mode using the migration guide

API

Simplified the URL API by removing the less-used GetAbsoluteURL(), since both GetURL() and GetAbsoluteURL() always returned absolute URLs

API

Extended the Network tab settings into resource collection settings for better control over tracked resources during inspection

Feature

Added shape-based hit testing for SVG content, enabling interaction based on the visible shape of graphics

Feature

Enabled GPU resource reuse by providing more information about created GPU resources. Added a special flag for some backend textures that marks them as temporary

Feature Unreal Engine

Added official support for Unreal Engine 5.8

Enhancement

Improved style resolution performance by resolving only changed properties and checking at the domain level instead of iterating over everything.

Enhancement

Improved performance markers by attaching better contextual data to each marker

Enhancement

Improved animated SVG performance by optimizing drawing surface cache reuse for background-image, mask-image, and <img> elements.

Enhancement

Added new GPU memory statistics fields for internal textures to provide insight into the usage frequency of a given resource

Enhancement

Added support for space-evenly in align-content and justify-content properties

Enhancement

Added full support for the pointer-events property

Enhancement

Made elementsFromPoint and elementForPoint to also collect SVG nodes

Enhancement

Made OnCaretRectChanged() to be called when the element receives focus, enabling additional IME functionality

Enhancement

Reduced overhead when a backdrop mask texture is set but no elements use backdrop filters

Enhancement

Extended custom effect float parameter handling to 16 parameters

Enhancement

Added handling for all sRGB DXGI texture formats in the DDS file decoding logic

Enhancement

Reduced the amount of mandatory options required to be passed when initializing Gameface

Enhancement

Forwarded V8 failures and check failures to the client log handler

Enhancement

Made content-related messages to appear in the inspector console

Enhancement

Added drag-and-drop functionality to the Player's bookmarks bar.

Enhancement

Added saving of the Player application's position and size between runs when using the GUI

Enhancement

Added IME support to the Player application

Enhancement

Introduced a cross-platform ITextTransformationManager implementation using the ICU module for the Player application and the samples

Enhancement

Added a parallax UI sample

Enhancement Unity

Optimized GPU texture memory usage by utilizing the render target pool for temporary textures

Enhancement Unity

Added a new event that notifies subscribers immediately after the native System is created

Enhancement Unity

Simplified font loading in Unity3D

Enhancement Unity

Added documentation and a sample for resource preloading in Unity3D

Enhancement Unity

Improved the provided C# backend in the Unity integration to allow multiple paths to be drawn at once

Enhancement Unreal Engine

Optimized GPU texture memory usage by utilizing the render target pool for temporary textures

Enhancement Unreal Engine

Added the ability to specify absolute paths for Resource Host Locations

Enhancement Unreal Engine

Improved the CPU performance of Paint calls by 10% by executing commands immediately

Fix

Made reactive variables that set element text content to work in Svelte

Fix

Made the textContent JSX attribute to work in Solid JS

Fix

Fixed sporadic crashes when inspecting SVG nodes through the inspector

Fix

Fixed a Win32-specific V8 crash when obtaining the current isolate.

Fix

Fixed a crash caused by incorrect ruleset IDs when copying rulesets

Fix

Fixed a crash that could occur when removing styles containing keyframe rules that share the same name

Fix

Fixed a crash that could occur when removing styles containing font-face rules that share the same font description (font-family, font-style, font-weight)

Fix

Fixed a crash that could occur when removing a <style> or <link> using a preloaded stylesheet containing media rules.

Fix

Fixed a crash in UnloadDocument when an immediate layout was invoked just beforehand

Fix

Fixed a potential crash when a user background is set but no view renderer is created

Fix

Fixed a bug in calculating the byte size of textures with multiple mip levels that caused crashes in the native DX11 backend

Fix

Fixed a crash when editing style elements in templates before adding them to the DOM

Fix

Fixed a crash while style matching descendants

Fix

Fixed a bug in the native Vulkan backend that caused crashes when using the GPU path tessellator

Fix

Fixed box-shadow anti-aliasing caused by subpixel positioning.

Fix

Fixed an inaccurate box-shadow blur calculation that resulted in a smaller blur radius

Fix

Fixed incorrect box-shadow rendering when both offsets and spread are specified.

Fix

Fixed incorrect box-shadow rendering with subpixel parameters.

Fix

Fixed incorrect inset box-shadow rendering when its size adds up to an odd number.

Fix

Fixed incorrect box-shadow rendering when it has negative spread and a rounded shape.

Fix

Fixed blurred box-shadows incorrectly clipping inside the element's border box when the element has a semi-transparent background-color.

Fix

Fixed inset box-shadows incorrectly clipping inside the element's border box when the element's border is a circle.

Fix

Fixed incorrect box-shadow rendering when dynamically changed through JavaScript or animations.

Fix

Fixed incorrect rendering of identical box-shadows used by multiple elements.

Fix

Fixed incorrect rounded rectangle box-shadow rendering when border radii differ between corners.

Fix

Fixed incorrect rounded border rendering when border radii exceed the width or height unevenly.

Fix

Fixed layout gaps making elements larger by creating a final gap at the end

Fix

Reduced inspector memory overhead caused by leaks when the inspector was enabled but not actively inspecting

Fix

Fixed a case-sensitivity bug in URL hashing that could prevent URL-based caches from working correctly.

Fix

Made frame statistics to be gathered only when requested by client code instead of always

Fix

Fixed frames where the same SVG resource was drawn for some users and skipped for others

Fix

Stopped parsing the flex shorthand when it contains more than three values

Fix

Fixed an issue where SVG elements did not render line caps correctly

Fix

Reduced the severity of a warning about unresolved custom variables, as this can occur naturally when loading a page.

Fix

Fixed invalid CSS variables to use inherited styles when the property inherits instead of always resetting to the initial value

Fix

Fixed incorrect parsing of the text-stroke shorthand when the value does not contain a text-stroke-width

Fix

Fixed incorrect parsing of the border shorthand when the value does not specify a border width

Fix

Fixed empty rules not being added to the stylesheet

Fix

Fixed transitions involving inherited properties

Fix

Fixed dynamic range matching for custom media queries

Fix

Fixed a memory release bug in the provided native backend for Nintendo Switch 2

Fix

Fixed a rare false-positive assertion failure when unregistering compositions

Fix

Fixed cases where GIFs used on the page triggered assertions

Fix Unity

Fixed warnings when using live views with URP in Unity3D

Rendering performance has been improved for animated elements using SVG's as mask-image, background-image, or <img/> tags by dynamically adjusting SVG surface cache re-use tolerances. This effectively eliminates unnecessary re-rendering, which has been shown to drop GPU processing times without impacting visual quality.

Added complete support for the pointer-events property

Section titled “Added complete support for the pointer-events property”

Previously, Gameface did not support precise shape-based hit-testing inside <svg> elements. Hits were evaluated against the rectangular bounding box of the <svg> element as a whole, and individual SVG shapes (such as <path>, <circle>, or <rect>) were not returned by hit-testing or JavaScript APIs. Additionally, SVG-specific values for the pointer-events CSS property (such as stroke, fill, visiblePainted, etc.) were not supported.

With this release, inline SVG elements now fully support precise shape-based hit-testing and the pointer-events property. Hit-testing is now calculated against the actual geometry of SVG shapes rather than their rectangular bounding boxes. This makes it possible to base JavaScript logic on precise shape hits (for example, triggering actions only when clicking the stroke or fill of an intricate vector path).

<!DOCTYPE html>
<html>
<head>
<style>
svg {
position: absolute;
width: 100px;
height: 100px;
top: 0px;
left: 0px;
pointer-events: none;
background-color: rgba(255, 0, 0, 0.5);
}
#strokeHittable {
pointer-events: stroke;
}
</style>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100" preserveAspectRatio="none">
<circle id="strokeHittable" cx="50" cy="50" r="25" stroke="orange" stroke-width="10" />
<circle id="notHittable" cx="50" cy="50" r="25" stroke="red" stroke-width="10" />
</svg>
<script>
const svg = document.querySelector("svg");
const circle = svg.querySelector("circle");
svg.addEventListener("click", e => {
console.log(e.target);
});
</script>
</body>
</html>

In the page above the following can be observed when clicking at various locations.

Click LocationResult
x=5 y=50Nothing is logged, as we have clicked outside of the circles, the <svg/> doesn't accept hits there and no events are dispatched.
x=25 y=50The <circle id="strokeHittable"/> is logged as we have clicked on its stroke, it accepts hits and an event is dispatched.
x=50 y=50Nothing is logged, as we have clicked on the fill of circles, nothing accepts hits there and no events are dispatched.

The elementFromPoint and elementsFromPoint functions now collect SVG nodes

Section titled “The elementFromPoint and elementsFromPoint functions now collect SVG nodes ”

Gameface now also collects SVG nodes in the elementFromPoint and elementsFromPoint JavaScript calls.

<!DOCTYPE html>
<html id="anHTML">
<head>
<style>
svg {
position: absolute;
width: 100px;
height: 100px;
top: 0px;
left: 0px;
}
div {
position: absolute;
width: 100px;
height: 100px;
top: 0px;
left: 0px;
background-color: rgba(255, 0, 0, 0.5);
}
</style>
</head>
<body>
<div id="aDiv"></div>
<svg id="anSvg" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"
preserveAspectRatio="none">
<circle id="anOrangeCircle" cx="50" cy="50" r="25" stroke="orange" stroke-width="10" />
<circle id="aRedCircle" cx="50" cy="50" r="25" stroke="red" stroke-width="10" />
</svg>
<script>
// Ensure layout has finished.
requestAnimationFrame(() => {
requestAnimationFrame(() => {
console.log(`document.elementsFromPoint(50, 50) = [ ${document.elementsFromPoint(50, 50).map(el => el.id).join(", ")} ]`);
console.log(`document.elementFromPoint(50, 50) = ${document.elementFromPoint(50, 50).id}`);
});
});
</script>
</body>
</html>

Running the page above will log the following as all SVG elements accept pointer events. Therefore, as the <div/> and the <svg/> overlap, all elements will be in elementsFromPoint and their order will be the paint order.

Info: document.elementsFromPoint(50, 50) = [ aRedCircle, anOrangeCircle, anSvg, aDiv, anHTML ]
Info: document.elementFromPoint(50, 50) = aRedCircle

Generate unique text nodes for whitespaces requested by JS

Section titled “Generate unique text nodes for whitespaces requested by JS”

Modern frameworks like Svelte and SolidJS rely on fine-grained reactivity, caching direct references to DOM elements to render efficiently. Previously, Gameface optimized performance by sharing a single whitespace node across JavaScript queries, which inadvertently interfered with how these frameworks handle updates. To ensure seamless compatibility, Gameface now generates unique Text nodes for whitespace elements whenever they are accessed via DOM traversal APIs (such as firstChild and nextSibling). As a result, reactive text updates in these frameworks now work as expected.

Optimize GPU memory by reusing internal textures

Section titled “Optimize GPU memory by reusing internal textures”

Gameface's rendering library now informs backends whether a texture's contents are only needed during the rendering execution that created them. Such textures can be fetched from your engine's Render Target pool when they are needed and immediately returned at the end of the frame. By releasing these textures back to the pool, other engine subsystems can share and reuse the same physical memory, reducing the overall GPU memory footprint. If your engine lacks a texture pooling mechanism, you can safely ignore this feature and continue using standard persistent allocations without affecting rendering. For more information see Reusing internal textures in custom engines.

If you want to achieve unique aesthetic effects — such as frosted glass, chromatic aberration, or holographic distortion — you can completely replace the default blur by providing a custom implementation. For more info you can check the Global Backdrop Filter page.

Previously, Gameface relied on Unity's Resources.LoadAll API to load fonts from a Resources/Fonts folder, which forced the entire binary data of all fonts into RAM at once. Gameface now natively streams font files directly from the disk using partial reads. This drastically reduces the memory footprint of the UI. See more in Font Preloading page.

A new OnNativeSystemCreated event has been added to the CohtmlUISystem component. This event fires the exact moment the native plugin IUISystem is successfully initialized, providing a safe, race-condition-free entry point to configure the native system before any views begin rendering.

Unity3D: BlurRadius Removed from CohtmlView component

Section titled “Unity3D: BlurRadius Removed from CohtmlView component”

The BlurRadius property has been removed from CohtmlView to decouple the core view from specific filter implementations. It now lives inside the default GlobalBackdropBlurFilter class. If you need to change the blur radius at runtime while using the default effect, you can access it through the renderer's active filter:

if (view.Renderer?.GlobalBackdropFilter is GlobalBackdropBlurFilter defaultFilter)
{
defaultFilter.BlurRadius = 12;
}

The InspectorNetworkTabMode enum was renamed to InspectorContextMode. You can now use it to enable or disable all tabs in the inspector, which require JS context (Console, Network, Performance, Memory). Before only the Network tab could be enabled/disabled.

Note: The Elements tab is unaffected by the option.

By default the option is set to Enabled.

Previously, a bug caused InspectorContextMode to be ignored, meaning tabs behaved as if AlwaysEnabled were set. As a result, error messages were collected and output to the Console tab even with no inspector connected. Now, by default, errors and messages will only appear once the inspector is connected.

If your workflow relies on errors and messages being available before an inspector connects, set InspectorContextMode to AlwaysEnabled.

Because of the new memory font loading optimizations, Gameface no longer automatically preloads fonts from the Resources/Fonts folder. If your project relied on this automatic loading, your text may disappear or fall back to the fallback font after updating. To migrate to the new, memory-efficient font pipeline:

  1. Relocate your Font Files: Move your font files out of Resources/Fonts and place them into your StreamingAssets/Cohtml/UIResources/Fonts folder (or wherever your UI assets are hosted).
  2. Restore Native File Extensions (Optional): You no longer need to rename your fonts to .bytes to trick Unity's Resource system. You can rename them back to their native .ttf or .otf extensions.
  3. Load Fonts via CSS (Recommended): The recommended way to use fonts in Gameface is by using @font-face declarations directly in your CSS. If you previously relied on Unity auto-loading your fonts globally, you should update your stylesheets to load them locally via @font-face.
  4. Register Fonts Manually: If you need to preload fonts or cannot use @font-face, you must explicitly register your fonts via the CohtmlUISystem API when the UI system initializes.

Changing the default color space for rendering to sRGB

Section titled “Changing the default color space for rendering to sRGB”

Previously, Gameface dynamically determined the rendering color space based on the format of the bound render target. In release 3.1, Gameface defaults to sRGB output (gamma space), and the linear rendering pipeline is officially deprecated.

This change stems from the fact that linear blending causes unexpected visual discrepancies for UI design. Modern web browsers, standard UI frameworks, and design tools (such as Figma) natively blend layers, text, and gradients in sRGB (gamma) space; forcing a linear pipeline causes transparencies and colors to look washed out compared to the original assets. By moving exclusively to an sRGB gamma-space pipeline, we ensure consistent blending behavior and a 1:1 match between your design tools and the final in-game result.

To ease the transition, we have introduced a compatibility flag: cohtml::CompatibilityFlags::VCF_AutoDetectColorSpaceFromRenderTarget. Enabling this flag temporarily restores the legacy, render-target-backed behavior while you update your integration.

For most integrations, the most straightforward migration path is to let Gameface handle internal rendering in gamma space while keeping your subsequent composition passes unchanged:

  1. Bind a Non-sRGB Render Target Format to SetRenderTarget()

    If you currently pass an _SRGB render target view to cohtml::ViewRenderer::SetRenderTarget(), switch it to its non-_SRGB equivalent (e.g., transition from renoir::PF_R8G8B8A8_SRGB to renoir::PF_R8G8B8A8, or from DXGI_FORMAT_R8G8B8A8_UNORM_SRGB to DXGI_FORMAT_R8G8B8A8_UNORM).

    This ensures Gameface writes gamma-encoded values directly. If you keep an _SRGB format bound here, the GPU will apply hardware sRGB encoding on top of Gameface's gamma output, resulting in double gamma correction.

  2. Keep Post-Composition Passes Unchanged (With Exceptions for HDR Formats)

    The texture written by Gameface will now explicitly contain gamma-encoded values. If your subsequent composition passes already sample this texture via an _SRGB Shader Resource View (SRV), the hardware will automatically decode it to linear values during sampling. No changes are needed here.

    • Handling HDR Formats (PF_R16G16B16A16 and PF_R32G32B32A32): Previously, Gameface wrote linear values into these high-bit-depth formats. Following this change, gamma-encoded values will be written instead. Because these formats do not support native _SRGB Shader Resource Views for hardware decoding, you must manually perform an SRGBToLinear conversion in your sampling/composition shader to continue using them as before.
  3. Update Custom Shaders (if applicable)

    If you use Gameface's provided shaders, no action is required. When images or external texture resources do not match the current pipeline mode, Gameface automatically raises the appropriate PSAF flags, and the shaders handle converting them to the target color space before executing any blending operations.

    However, if you are using custom shaders, you will need to mimic this logic and update your color space transformations:

    • Remove sRGB -> Linear conversions: The PSAF_LinearColorSpace flag will no longer be active. You can safely remove shader code that converts sampled textures from sRGB to Linear (e.g., SRGBToLinear invocations).
    • Add Linear -> sRGB conversions: For any input textures that are explicitly authored or stored in Linear color space, you must now convert them to sRGB space within your shader (e.g., using LinearToSRGB).

Consolidated URL accessor on IAsyncResourceRequest

Section titled “Consolidated URL accessor on IAsyncResourceRequest”

The cohtml::IAsyncResourceRequest interface previously had two methods that both returned the absolute URL — GetURL() and GetAbsoluteURL() — creating ambiguity about which to use. These have been consolidated into a single GetURL(), which will always return the absolute URL of the request.

If you were using GetAbsoluteURL(), replace it with GetURL(). Behavior is unchanged.