HDR

With version 1.14 Cohtml becomes capable of rendering HDR content and using wider colors in the scRGB color space. With that, several new features are being introduced.

Before reading about the Prysm support for HDR, you may want to familiarize yourself with the key concept in HDR from the HDR primer.

Wide texture formats

There are two new pixel formats – renoir::PF_R16G16B16A16 and renoir::PF_R32G32B32A32. Those represent floating-point textures with 16 and 32 bits per channel respectively. All backends now support the creation of textures with these formats.

Wide render targets

The new texture formats can also be used as render targets. 16 and 32-bit textures are suitable for rendering HDR content as color values above 1.0 won’t be clipped and will be preserved.

To use 16 (or 32) bit texture as a render target, you have to pass the appropriate render target and depth stencil objects together with a renoir::Texture2D object describing the texture to the SetRenderTarget method of the ViewRenderer. The relevant fields of the renoir::Texture2D struct are Width, Height, SamplesCount, and Format which can be renoir::PF_R8G8B8A8, renoir::PF_R16G16B16A16, or renoir::PF_R32G32B32A32. Only these three are supported as render target formats for Prysm.

The following example illustrates how a 16-bit render target can be set when the DirectX 11 backend is in use.


renoir::Texture2D description;
description.Width = 1280;
description.Height= 720;
description.SamplesCount = 1;
description.Format = renoir::PF_R16G16B16A16;

m_ViewRenderer->SetRenderTarget(pRenderTargetView,
    pDepthStencilView, description);

It is important to note that pRenderTargetView has to be a Render Target View of a user-created texture with DXGI_FORMAT R16G16B16A16 format. Setting a 16-bit render target to the ViewRenderer causes all internal render targets that Cohtml uses to also be 16-bit.

Switching the format of a render target of a view with a new call to SetRenderTarget is possible but comes with a high cost as there are several internal caches that have to be reset with textures of the new format. The time for switching the render target format should be comparable to initializing the view.

Floating-point color

With the support for HDR content, the internal representation of color changes to four floating-point numbers. This increases the accuracy of the colors and allows color values above 1.0 to be represented.

HDR CSS color definition

Per standard, color values above 255 defined through rgb()`rgba()` in CSS are clamped in the range [0.0-1.0]. This is obviously undesirable for HDR colors.

In order for the HDR rendering to be usable through CSS, we’ve introduced a new way of defining color values. We base the color definition on the Working Draft for the CSS Color Module Level 4.

The new way for defining colors with values that can go over 1.0 is through color(color-space r g b [a]). color-space is a string defining the color space and how the color values should be interpreted. The color values themselves are floating-point numbers and depending on the color space will or will not be clamped.

Currently, Cohtml supports only two color spaces that make the most sense for game development – scRGB and Rec.2020. scRGB is compatible with the standard sRGB and simply allows color above 1.0 without doing any transformations on them. You can use this color space in CSS like:


.hdr-block {
    background-color: color(coh-scrgb 2.0 2.0 2.0 1.0)
}
...

<div class="hdr-block">The background has HDR color.</div>

The prefix coh- is there because the scRGB space is not in the CSS Draft for the color definitions.

In the example, if a 16-bit texture is used as a render target for the corresponding view, the color (2.0, 2.0, 2.0, 1.0) will be used to render the element and this will be the color value written in the render target.

When it comes to the other supported color space, Rec.2020, the color defined in it will be first transformed into scRGB through the appropriate linear transformation. Example usage of this color space is:

.hdr-block {
    background-color: color(rec2020 2.0 3.5 2.0 1.0)
}

...

<div class="hdr-block">The background has HDR color.</div>