Verwenden von DirectX mit Anzeige mit hohem dynamischen Bereich und erweiterter Farbe
Dieses Thema bietet eine technische Übersicht über die Ausgabe von Direct3D 11- und Direct3D 12-Inhalten mit hohem dynamischen Bereich (HDR) an eine HDR10-Anzeige mithilfe Windows 10 erweiterter Farbunterstützung. Es werden einige wichtige konzeptionelle Unterschiede zwischen der Ausgabe an HDR10-Displays im Vergleich zu herkömmlichen SDR-Standardanzeigen (Dynamic Range) zusammengefasst. Außerdem werden die wichtigsten technischen Anforderungen für Ihre App zur ordnungsgemäßen Unterstützung Windows erweiterten Farbe sowie Empfehlungen und bewährte Methoden behandelt.
Einführung
Windows 10 unterstützt HDR und andere erweiterte Farbanzeigen, die eine deutlich höhere Farbtreue als herkömmliche SDR-Displays bieten. Sie können Direct3D, Direct2D und andere Grafik-APIs verwenden, um HDR-Inhalte auf einer fähigen Anzeige zu rendern.
Windows erweiterte Farbe bezieht sich auf mehrere verwandte Technologien, die erstmals mit Windows 10 Version 1703 eingeführt wurden und Unterstützung für Displays bieten, die die Farbfunktionen herkömmlicher SDR-Standardanzeigen (Dynamic Range) überschreiten. Die drei wichtigsten erweiterten Funktionen werden unten beschrieben. Der gängigste Typ der erweiterten Farbanzeige, HDR10, unterstützt alle drei erweiterten Funktionen.
Hoher dynamischer Bereich
Dynamischer Bereich bezieht sich auf den Unterschied zwischen der maximalen und minimalen Leuchtdichte in einer Szene. dies wird häufig in Nits (Candelas pro Quadratzentimeter) gemessen. Szenen in der realen Welt, z. B. dieser Untergang, weisen häufig dynamische Bereiche von 10 Größenordnungen der Leuchtdichte auf. das menschliche Auge kann nach der Anpassung einen noch größeren Bereich erkennen.

Seit Direct3D 9 können Grafik-Engines ihre Szenen intern mit dieser physisch genauen Genauigkeit rendern. Ein typischer dynamischer Standardbereich kann jedoch nur etwas mehr als 3 Größenordnungen der Leuchtdichte reproduzieren. Daher mussten alle in HDR gerenderten Inhalte in den eingeschränkten Bereich der Anzeige toniert (komprimiert) werden. Neue HDR-Anzeigen, einschließlich derjenigen, die dem HDR10-Standard (BT.2100) entsprechen, durchbrechen diese Einschränkung.
Breite Farbpalette mit automatischer Systemfarbverwaltung
Farbskala bezieht sich auf den Bereich und die Sättigung von Farbtons, die eine Anzeige reproduzieren kann. Die am stärksten überlastete natürliche Farbe, die das menschliche Auge erkennen kann, ist reines monokonservantes Licht, z. B. das, was von einem Laser erzeugt wird. Die Anzeige von Mainstream-Consumern kann Farben jedoch häufig nur innerhalb des sRGB-Gamuts reproduzieren, was nur etwa 35 % aller für Menschen lesbaren Farben darstellt. Das folgende Diagramm ist eine Darstellung des menschlichen "menschlichen Locus" oder aller erkennbaren Farben (auf einer bestimmten Leuchtdichtestufe), wobei das kleinere Dreieck der sRGB-Gamut ist.

High-End-, professionelle PC-Displays verfügen über lange unterstützte Farbpaletten, die deutlich breiter als sRGB sind, z. B. Adobe RGB und D65-P3. Und diese breiten Gamutanzeigen werden immer häufiger angezeigt. Vor der erweiterten Farbe führten Windows jedoch keine Farbverwaltung auf Systemebene für Anwendungen durch. Dies bedeutete Folgendes: Wenn eine DirectX-App z. B. ein reines Rot oder RGB(1.0, 0.0, 0.0) in ihre Austauschkette gerendert hat, würde Windows einfach das am stärksten verstrichene Rot überprüfen, das die Anzeige reproduzieren konnte, unabhängig von der tatsächlichen Farbskala der Anzeige.
Apps, die eine hohe Farbgenauigkeit benötigten, könnten die Farbfunktionen der Anzeige abfragen (z. B. mitHILFE von CAB-Profilen) und eine eigene prozessbezogene Farbverwaltung durchführen, um die Farbpalette der Anzeige korrekt zu bestimmen. Die überwiegende Mehrheit der Apps und visuellen Inhalte geht jedoch davon aus, dass es sich bei der Anzeige um sRGB handelt, und sie verlassen sich auf das Betriebssystem, um diese Annahme zu erfüllen.
Windows erweiterte Farbe fügt die automatische Farbverwaltung auf Systemebene hinzu. Der Desktopfenster-Manager (DWM) ist Windows Compositor. Wenn erweiterte Farben aktiviert sind, führt der DWM eine explizite Farbkonvertierung vom Farbraum des visuellen App-Inhalts in einen kanonischen Kompositionsfarbraum (scRGB) durch. Windows konvertiert dann den zusammengesetzten Framepufferinhalt in den nativen Farbraum der Anzeige. Auf diese Weise erhalten herkömmliche sRGB-Inhalte automatisch farbgenaues Verhalten, während erweiterte farbfähige Apps die Vollfarbfunktionen der Anzeige nutzen können.
Tiefe Genauigkeit/Bittiefe
Numerische Genauigkeit oder Bittiefe bezieht sich auf die Darstellung oder Unterscheidung zwischen ähnlichen, aber unterschiedlichen Farben ohne Banding oder Artefakte. Der Standard-PC unterstützt 8 Bits pro Farbkanal, während das menschliche Auge mindestens 10 bis 12 Bit Genauigkeit erfordert, um ermittelbare Verzerrungen zu vermeiden, ohne auf Techniken wie Dithering oder je nach Anzeigebedingungen zurückzugreifen.

Vor der erweiterten Farbe beschränkte DWM Fenster-Apps, um Inhalte nur mit 8 Bit pro Farbkanal auszugeben, auch wenn die Anzeige eine höhere Bittiefe unterstützte. Wenn erweiterte Farben aktiviert sind, führt der DWM seine Komposition mithilfe des IEEE-Gleitkommawerts mit halber Genauigkeit (FP16) aus, um Engpässe zu beseitigen und die verwendung der vollständigen Genauigkeit der Anzeige zu ermöglichen.
Systemanforderungen
Betriebssystem
Die erweiterte Farbunterstützung wurde zuerst mit Windows 10, Version 1703, ausgeliefert und mit jedem Update erheblich verbessert. In diesem Thema wird davon ausgegangen, dass Ihre App auf Windows 10 Version 1903 oder höher abzielt.
Anzeige
Um einen hohen dynamischen Bereich nutzen zu können, benötigen Sie eine Anzeige, die den HDR10-Standard unterstützt. Windows funktioniert am besten mit Anzeigen, die VESA DisplayHDR-zertifiziertsind.
Grafikprozessor (GPU)
Eine aktuelle GPU ist erforderlich. Um HDR10-Anzeigen zu unterstützen, erfordert Windows 10 eine der folgenden Angaben.
- Nvidia GeForce 1000-Serie (Pascal) oder neuer
- AMD Rx 400-Serie (Polaris) oder neuer
- Ausgewählte Intel Core 7-Serie (Kaby Lake) oder neuer
Beachten Sie, dass je nach Szenario zusätzliche Hardwareanforderungen gelten, einschließlich Hardwarecodecbeschleunigung (10-Bit-HEVC, 10-Bit-VP9 usw.) und PlayReady-Unterstützung (SL3000). Wenden Sie sich an Ihren GPU-Anbieter, um spezifischere Informationen zu erhalten.
Grafiktreiber (WDDM)
Der neueste verfügbare Grafiktreiber wird dringend empfohlen, entweder von Windows Update oder von der Website des GPU-Herstellers oder PC-Herstellers. Für Windows 10 Version 1903 und höher empfehlen wir Treiber, die mindestens Windows WDDM(Display Driver Model) Version 2.6 unterstützen.
Unterstützte Rendering-APIs
Windows 10 unterstützt eine Vielzahl von Rendering-APIs und -Frameworks. Die erweiterte Farbunterstützung basiert im Wesentlichen darauf, dass Ihre App eine moderne Präsentation mit DXGI oder den Visual Layer-APIs durchführen kann.
Daher kann jede Rendering-API, die eine dieser Präsentationsmethoden ausgeben kann, erweiterte Farben unterstützen. Dies schließt ein, ist aber nicht darauf beschränkt.
- Direct3D 11
- Direct3D 12
- Direct2D
- Win2D
- Erfordert die Verwendung der CanvasSwapChain- oder CanvasSwapChainPanel-APIs auf niedrigerer Ebene.
- Windows.UI.Input.Inking
- Unterstützt benutzerdefiniertes Rendern von Dry Ink mit DirectX.
- XAML
- Unterstützt die Wiedergabe von HDR-Videos mit MediaPlayerElement.
- Unterstützt die Decodierung von JPEG-XR-Bildern mithilfe des Image-Elements.
- Unterstützt DirectX-Interop mit SwapChainPanel.
Behandeln dynamischer Anzeigefunktionen
Windows 10 unterstützt eine enorme Bandbreite erweiterter farbfähiger Displays, von leistungseffizienten integrierten Panels bis hin zu High-End-Gamingmonitoren und TVs. Windows Benutzer erwarten, dass Ihre App alle diese Variationen nahtlos verarbeitet, einschließlich der überall vorhandenen SDR-Anzeigen.
Windows 10 bietet dem Benutzer die Kontrolle über HDR und erweiterte Farbfunktionen. Ihre App muss die Konfiguration der aktuellen Anzeige erkennen und dynamisch auf Funktionsänderungen reagieren. Dies kann aus vielen Gründen auftreten, z. B. weil der Benutzer ein Feature aktiviert oder deaktiviert oder die App zwischen verschiedenen Anzeigen verschoben hat oder sich der Energiezustand des Systems geändert hat.
Universelle Windows-Plattform-Apps (UWP)
Wenn Sie eine UWP-App schreiben, verwenden Sie AdvancedColorInfo, um Anzeigefunktionen unabhängig von der verwendeten Grafikrendering-API zu erhalten. Rufen Sie eine Instanz von AdvancedColorInfo aus DisplayInformation::GetAdvancedColorInfoab.
Um zu überprüfen, welche erweiterte Farbart derzeit aktiv ist, verwenden Sie die CurrentAdvancedColorKind-Eigenschaft. In Windows 10 Version 1903 und höher gibt dies einen von drei möglichen Werten zurück: SDR, WCG oder HDR. Dies ist die wichtigste zu überprüfende Eigenschaft, und Sie sollten Ihre Render- und Präsentationspipeline als Reaktion auf die aktive Art konfigurieren.
Um zu überprüfen, welche erweiterten Farbarten unterstützt, aber nicht notwendigerweise aktiv sind, rufen Sie IsAdvancedColorKindAvailable auf. Sie können diese Informationen beispielsweise verwenden, um den Benutzer aufzufordern, zur Windows Einstellungen-App zu navigieren, damit er HDR oder WCG aktivieren kann.
Die anderen Member von AdvancedColorInfo stellen quantitative Informationen zum physischen Farbvolumen des Panels (Leuchtdichte und Chromeinanz) bereit, die den statischen HDR-Metadaten von SMPTE ST.2086 entsprechen. Verwenden Sie diese Informationen, um die HDR-Tonmapping- und Gamutzuordnung Ihrer App zu konfigurieren.
Registrieren Sie sich für das AdvancedColorInfoChanged-Ereignis, um Änderungen an erweiterten Farbfunktionen zu verarbeiten. Dieses Ereignis wird ausgelöst, wenn sich ein Parameter der erweiterten Farbfunktionen der Anzeige aus irgendeinem Grund ändert.
Behandeln Sie dieses Ereignis, indem Sie eine neue Instanz von AdvancedColorInfo abrufen und überprüfen, welche Werte geändert wurden.
Desktop-DirectX-Apps (Win32)
Wenn Sie eine Win32-App schreiben und DirectX zum Rendern verwenden, verwenden Sie DXGI_OUTPUT_DESC1, um Anzeigefunktionen abzurufen. Rufen Sie eine Instanz dieser Struktur über IDXGIOutput6::GetDesc1ab.
Um zu überprüfen, welche erweiterte Farbart derzeit aktiv ist, verwenden Sie die ColorSpace-Eigenschaft vom Typ DXGI_COLOR_SPACE_TYPE, die einen der folgenden Werte enthält:
- DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, SDR
- DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020, HDR
Hinweis
Andere erweiterte Farbarten wie WCG werden von DXGI als SDR behandelt. Sie können DXGI nicht verwenden, um eine WCG-Anzeige zu identifizieren.
Hinweis
MIT DXGI können Sie nicht überprüfen, welche erweiterten Farbarten unterstützt werden, aber derzeit nicht aktiv sind.
Die meisten anderen Member von DXGI_OUTPUT_DESC1 quantitative Informationen zum physischen Farbvolumen des Panels (Leuchtdichte und Chrominance), die den statischen HDR-Metadaten von SMPTE ST.2086 entspricht. Sie sollten diese Informationen verwenden, um die HDR-Tonmapping- und Gamutzuordnung Ihrer App zu konfigurieren.
Win32-Apps verfügen nicht über einen nativen Mechanismus, um auf erweiterte Farbfunktionsänderungen zu reagieren. Wenn Ihre App stattdessen eine Renderschleife verwendet, sollten Sie IDXGIFactory1::IsCurrent mit jedem Frame abfragen. Wenn FALSE zurückgegeben wird, sollten Sie eine neue DXGI_OUTPUT_DESC1 abrufen und überprüfen, welche Werte sich geändert haben.
Darüber hinaus sollte Ihr Win32-Nachrichtenpump die WM_SIZE verarbeiten. Dies bedeutet, dass Ihre App möglicherweise zwischen verschiedenen Displays verschoben wurde.
Hinweis
Um eine neue DXGI_OUTPUT_DESC1 zu erhalten, müssen Sie die aktuelle Anzeige abrufen. Sie sollten IDXGISwapChain::GetContainingOutput jedoch nicht aufrufen. Dies liegt daran, dass Swapketten eine veraltete DXGI-Ausgabe zurückgeben, sobald DXGIFactory::IsCurrent false ist, und das erneute Erstellen der Swapkette, um eine aktuelle Ausgabe zu erhalten, führt zu einem temporären schwarzen Bildschirm. Stattdessen wird empfohlen, die Grenzen aller DXGI-Ausgaben zu durchzählen und zu ermitteln, welche die größte Schnittmenge mit den Begrenzungen Ihres App-Fensters auf hat.
Das folgende Codebeispiel stammt aus dem DirectX-Graphics-Samples-Repository.
// Retrieve the current default adapter.
ComPtr<IDXGIAdapter1> dxgiAdapter;
ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, &dxgiAdapter));
// Iterate through the DXGI outputs associated with the DXGI adapter,
// and find the output whose bounds have the greatest overlap with the
// app window (i.e. the output for which the intersection area is the
// greatest).
UINT i = 0;
ComPtr<IDXGIOutput> currentOutput;
ComPtr<IDXGIOutput> bestOutput;
float bestIntersectArea = -1;
while (dxgiAdapter->EnumOutputs(i, ¤tOutput) != DXGI_ERROR_NOT_FOUND)
{
// Get the retangle bounds of the app window
int ax1 = m_windowBounds.left;
int ay1 = m_windowBounds.top;
int ax2 = m_windowBounds.right;
int ay2 = m_windowBounds.bottom;
// Get the rectangle bounds of current output
DXGI_OUTPUT_DESC desc;
ThrowIfFailed(currentOutput->GetDesc(&desc));
RECT r = desc.DesktopCoordinates;
int bx1 = r.left;
int by1 = r.top;
int bx2 = r.right;
int by2 = r.bottom;
// Compute the intersection
int intersectArea = ComputeIntersectionArea(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2);
if (intersectArea > bestIntersectArea)
{
bestOutput = currentOutput;
bestIntersectArea = static_cast<float>(intersectArea);
}
i++;
}
// Having determined the output (display) upon which the app is primarily being
// rendered, retrieve the HDR capabilities of that display by checking the color space.
ComPtr<IDXGIOutput6> output6;
ThrowIfFailed(bestOutput.As(&output6));
DXGI_OUTPUT_DESC1 desc1;
ThrowIfFailed(output6->GetDesc1(&desc1));
Einrichten der DirectX-Swapkette
Nachdem Sie ermittelt haben, dass die Anzeige derzeit erweiterte Farbfunktionen unterstützt, konfigurieren Sie Ihre Auslagerungskette wie folgt.
Verwenden eines Flip-Präsentationsmodelleffekts
Beim Erstellen der Swapkette mit createSwapChainFor[Hwnd| Komposition| CoreWindow]-Methoden: Sie müssen das DXGI-Flip-Modell verwenden, indem Sie entweder die Option DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL oder DXGI_SWAP_EFFECT_FLIP_DISCARD auswählen. Dadurch ist Ihre Swapkette für die erweiterte Farbverarbeitung über DWM und verschiedene Optimierungen im Vollbildmodus geeignet. Weitere Informationen finden Sie im Thema For best performance, use DXGI flip model (DxGI-Flip-Modell für optimale Leistung).
Option 1. Verwenden des FP16-Pixelformats und des scRGB-Farbraums
Windows 10 unterstützt zwei Hauptkombinationen aus Pixelformat und Farbraum für erweiterte Farben. Wählen Sie eins basierend auf den spezifischen Anforderungen Ihrer App aus.
Für allgemeine Apps empfiehlt es sich, beim Erstellen der Swapkette DXGI_FORMAT_R16G16B16A16_FLOAT. Dies wird in Ihrer Datei auch als FP16 DXGI_SWAP_CHAIN_DESC1. Standardmäßig wird eine Swapkette, die mit einem Gleitkommapixelformat erstellt wurde, so behandelt, als würde sie den DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709-Farbraum verwenden, der auch als scRGB bezeichnet wird.
Mit dieser Kombination erhalten Sie den numerischen Bereich und die Genauigkeit, um nahezu jede physisch mögliche Farbe anzugeben und beliebige Verarbeitungen einschließlich Blending durchzuführen. Wenn Sie außerdem Direct2D, Win2D oder Windows.UI.Composition verwenden, ist dies die einzige unterstützte Kombination für alle Austauschketten oder Zwischenziele, die erweiterte Farbinhalte enthalten.
Der Wichtigste Kompromiss dieser Option ist, dass sie 64 Bits pro Pixel verbraucht, was die GPU-Bandbreite und den Arbeitsspeicherverbrauch im Vergleich zu den herkömmlichen UINT8 SDR-Pixelformaten verdoppelt. Darüber hinaus verwendet scRGB numerische Werte, die sich außerhalb des normalisierten Bereichs [0, 1] befinden, um Farben zu darstellen, die außerhalb des sRGB-Gamuts und/oder größer als 80 Leuchtdichten liegen. Beispielsweise codiert scRGB (1.0, 1.0, 1.0) das Standard-D65-Weiß bei 80 00 Grad; scRGB (12.5, 12.5, 12.5) codiert jedoch dasselbe D65-Weiß mit deutlich besseren 1.000 1000 000 000. Einige Grafikvorgänge erfordern einen normalisierten numerischen Bereich, und Sie müssen entweder den Vorgang ändern oder Farbwerte neu normalisieren.
Option 2: Verwenden des UINT10/RGB10-Pixelformats und des HDR10/BT.2100-Farbraums
Für Apps, die HDR10-codierte Inhalte nutzen, z. B. Media Player, oder Apps, die voraussichtlich hauptsächlich in Vollbildszenarien wie Spielen verwendet werden, sollten Sie beim Erstellen der Swapkette erwägen, DXGI_FORMAT_R10G10B10A2_UNORM inDXGI_SWAP_CHAIN_DESC1. Standardmäßig wird dies als Verwendung des sRGB-Farbraums behandelt. Daher müssen Sie IDXGISwapChain3::SetColorSpace1explizit aufrufen und als Farbraum DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020festlegen, auch bekannt als HDR10/BT.2100.
Diese Kombination hat strengere Einschränkungen als FP16. Sie können dies nur mit Direct3D 11 oder Direct3D 12 verwenden. Darüber hinaus gelten für UINT10/HDR10 Einschränkungen als Zwischenformat, da es die EOTF-Funktion ST.2084 ("gamma") verwendet, die stark nicht linear und als Kabelformat optimiert ist und nur 2 Bits Alpha bietet.
Diese Kombination kann jedoch leistungsstarke Leistungsoptimierungen bieten, wenn sie in der endgültigen Ausgabe Ihrer App verwendet wird. Es verbraucht die gleichen 32 Bits pro Pixel wie herkömmliche UINT8 SDR-Pixelformate. Darüber hinaus kann das Betriebssystem in bestimmten Vollbildszenarien die Leistung optimieren, indem die HDR10-Oberfläche direkt gescannt wird.
Verwenden einer erweiterten Farbwechselkette, wenn sich die Anzeige im SDR-Modus befindet
Sie können eine erweiterte Farbwechselkette auch dann verwenden, wenn die Anzeige einige oder alle erweiterten Farbfunktionen, die für Ihre Inhalte erforderlich sind, nicht unterstützt. In diesen Fällen wird der Desktopfenster-Manager (DWM) Ihre Inhalte auf die Funktionen der Anzeige herabkonvertiert. In Windows 10 Version 1903 und höher werden numerische Beschneidungswerte verwendet. Wenn Sie beispielsweise in eine FP16 scRGB-Swapkette rendern, wird alles außerhalb des numerischen Bereichs [0, 1] abgeschnitten.
Dieses Downconversionsverhalten tritt auch auf, wenn Ihr App-Fenster zwei oder mehr Anzeigen mit unterschiedlichen erweiterten Farbfunktionen umstreift. AdvancedColorInfo und IDXGIOutput6 werden abstrahiert, um nur die Merkmale der Hauptanzeige zu melden (definiert als die Anzeige, die die Mitte des Fensters enthält).
Korrektes Rendern von SDR-Inhalten mit SDR-Referenz auf weißer Ebene
In vielen Szenarien möchte Ihre App sowohl SDR- als auch HDR-Inhalte rendern. Beispielsweise das Rendern von Untertiteln oder Transportsteuerelementen über HDR-Videos oder die Benutzeroberfläche in einer Spielszene. Es ist wichtig, das Konzept des SDR-Referenz-Whitelevels zu verstehen, um sicherzustellen, dass Ihr SDR-Inhalt auf einer HDR-Anzeige korrekt aussieht.
Windows BEHANDELT HDR-Inhalte als Szenenbespricht, was bedeutet, dass ein bestimmter Farbwert auf einer bestimmten Leuchtdichteebene angezeigt werden sollte. Beispielsweise codieren scRGB (1.0, 1.0, 1.0) und HDR10 (497, 497, 497) genau D65 weiß bei 80 Leuchtdichten. In der Zwischenzeit wurde auf SDR-Inhalte üblicherweise eine Ausgabe verwiesen (oder auf die Anzeige verwiesen), was bedeutet, dass ihre Leuchtdichte dem Benutzer oder dem Gerät bleibt. Beispielsweise codiert sRGB (1.0, 1.0, 1.0) D65 weiß wie in den HDR-Beispielen, aber bei jeder maximalen Leuchtdichte, für die die Anzeige konfiguriert ist. Windows kann der Benutzer die White-Ebene des SDR-Verweises an seine Vorlieben anpassen. dies ist die Leuchtdichte, Windows sRGB (1.0, 1.0, 1.0) rendert. Auf HDR-Desktopmonitoren werden SDR-Referenz-White-Ebenen in der Regel auf ca. 200 Grad festgelegt.
Hinweis
Auf einer Anzeige, die eine Helligkeitssteuerung unterstützt, z. B. auf einem Laptop, passt Windows auch die Leuchtdichte von HDR-Inhalten (szenenspezifische Inhalte) an die gewünschte Helligkeitsstufe des Benutzers an. Dies ist für die App jedoch nicht sichtbar. Wenn Sie nicht versuchen, eine bitgenaue Wiedergabe des HDR-Signals zu gewährleisten, können Sie dies im Allgemeinen ignorieren.
Wenn Ihre App SDR und HDR immer auf separaten Oberflächen rendert und auf der Betriebssystemkomposition basiert, führt Windows automatisch die richtige Anpassung durch, um DEN SDR-Inhalt auf die gewünschte weiß-Ebene zu erhöhen. Wenn Ihre App z. B. XAML verwendet und HDR-Inhalte in einer eigenen SwapChainPanel-Datei rendert.
Wenn Ihre App jedoch ihre eigene Zusammensetzung von SDR- und HDR-Inhalten in einer einzelnen Oberfläche ausführt, sind Sie selbst dafür verantwortlich, die Anpassung des SDR-Referenz-Whitelevels selbst zu übernehmen. Andernfalls kann der SDR-Inhalt unter Annahme typischer Desktopanzeigebedingungen zu abgeblendet erscheinen. Zuerst müssen Sie den aktuellen SDR-Verweis auf weißer Ebene abrufen und dann die Farbwerte aller SDR-Inhalte anpassen, die Sie rendern.
Schritt 1: Abrufen der aktuellen SDR-Referenz auf weißer Ebene
Derzeit können nur UWP-Apps die aktuelle SDR-Referenzebene über AdvancedColorInfo.SdrWhiteLevelInNits abrufen. Für diese API ist ein CoreWindow erforderlich.
Schritt 2: Anpassen von Farbwerten des SDR-Inhalts
Windows definiert die nominale bzw. Standard-Verweis white-Ebene bei 80 Grad; Wenn Sie also einen standardmäßigen sRGB (1.0, 1.0, 1.0) weiß in eine FP16-Austauschkette rendern würden, würde er bei 80 30 Grad Leuchtdichte reproduziert werden. Um den tatsächlichen benutzerdefinierten Referenz-White-Level zu erreichen, müssen Sie den SDR-Inhalt von 80 -80-Grad auf die über AdvancedColorInfo.SdrWhiteLevelInNits angegebene Ebene anpassen.
Wenn Sie renderingen, indem Sie FP16 und scRGB oder einen Farbraum verwenden, der lineares Gamma (1,0) verwendet, können Sie einfach den SDR-Farbwert mit AdvancedColorInfo.SdrWhiteLevelInNits / 80 multiplizieren. Wenn Sie Direct2D verwenden, gibt es eine vordefinierte Konstante D2D1_SCENE_REFERRED_SDR_WHITE_LEVEL ,die über den Wert 80 verfügt.
D2D1_VECTOR_4F inputColor; // Input SDR color value.
D2D1_VECTOR_4F outputColor; // Output color adjusted for SDR white level.
auto acInfo; // AdvancedColorInfo
float sdrAdjust = acInfo->SdrWhiteLevelInNits / D2D1_SCENE_REFERRED_SDR_WHITE_LEVEL;
// Normally in DirectX, color values are manipulated in shaders on GPU textures.
// This example performs scaling on a CPU color value.
outputColor.r = inputColor.r * sdrAdjust; // Assumes linear gamma color values.
outputColor.g = inputColor.g * sdrAdjust;
outputColor.b = inputColor.b * sdrAdjust;
outputColor.a = inputColor.a;
Wenn Sie mit einem nicht linearen Gammafarbraum wie HDR10 rendern, ist die Anpassung des SDR-Weißpegels komplexer. Wenn Sie Einen eigenen Pixels shader schreiben, sollten Sie die Konvertierung in lineares Gamma erwägen, um die Anpassung anzuwenden.
Anpassen von HDR-Inhalten an die Funktionen der Anzeige mithilfe von Tonmapping
HDR- und erweiterte Farbanzeigen variieren stark in Bezug auf ihre Funktionen. Beispielsweise die minimale und maximale Leuchtdichte und die Farb gamut, die sie reproduzieren können. In vielen Fällen enthält Ihr HDR-Inhalt Farben, die die Funktionen der Anzeige überschreiten. Für die beste Bildqualität ist es wichtig, dass Sie HDR-Tonmapping durchführen, um den Farbbereich so zu komprimieren, dass er an die Anzeige passt, während die visuelle Absicht des Inhalts am besten beibehalten wird.
Der wichtigste einzelne Parameter für die Anpassung ist die maximale Leuchtdichte, die auch als MaxCLL (Content Light Level) bekannt ist. Anspruchsvollere Tonmapper passen auch min ludominanz (MinCLL) und/oder Farbprimionen an.
Schritt 1: Anzeigen der Farbvolumenfunktionen der Anzeige
Universelle Windows-Plattform-Apps (UWP)
Verwenden Sie AdvancedColorInfo, um das Farbvolumen der Anzeige zu erhalten.
Win32-DirectX-Apps (Desktop)
Verwenden DXGI_OUTPUT_DESC1, um das Farbvolumen der Anzeige zu erhalten.
Schritt 2: Informationen zum Farbvolumen des Inhalts
Je nachdem, woher Ihre HDR-Inhalte stammten, gibt es mehrere möglichkeiten, die Luminanz- und Farb gamut-Informationen zu bestimmen. Bestimmte HDR-Video- und Bilddateien enthalten SMPTE ST.2086-Metadaten. Wenn Ihr Inhalt dynamisch gerendert wurde, können Sie möglicherweise Szeneninformationen aus den internen Renderingstufen extrahieren, z. B. die hellste Lichtquelle in einer Szene.
Eine allgemeinere, aber rechenintensive Lösung besteht in der Ausführung eines Histogramms oder eines anderen Analyseüberlaufs auf dem gerenderten Frame. Das Direct2D Advanced Color Images SDK-Beispiel veranschaulicht dies mit Direct2D. die relevantesten Codeausschnitte sind unten aufgeführt:
// Perform histogram pipeline setup; this should occur as part of image resource creation.
// Histogram results in no visual output but is used to calculate HDR metadata for the image.
void D2DAdvancedColorImagesRenderer::CreateHistogramResources()
{
auto context = m_deviceResources->GetD2DDeviceContext();
// We need to preprocess the image data before running the histogram.
// 1. Spatial downscale to reduce the amount of processing needed.
DX::ThrowIfFailed(
context->CreateEffect(CLSID_D2D1Scale, &m_histogramPrescale)
);
DX::ThrowIfFailed(
m_histogramPrescale->SetValue(D2D1_SCALE_PROP_SCALE, D2D1::Vector2F(0.5f, 0.5f))
);
// The right place to compute HDR metadata is after color management to the
// image's native colorspace but before any tonemapping or adjustments for the display.
m_histogramPrescale->SetInputEffect(0, m_colorManagementEffect.Get());
// 2. Convert scRGB data into luminance (nits).
// 3. Normalize color values. Histogram operates on [0-1] numeric range,
// while FP16 can go up to 65504 (5+ million nits).
// Both steps are performed in the same color matrix.
ComPtr<ID2D1Effect> histogramMatrix;
DX::ThrowIfFailed(
context->CreateEffect(CLSID_D2D1ColorMatrix, &histogramMatrix)
);
histogramMatrix->SetInputEffect(0, m_histogramPrescale.Get());
float scale = sc_histMaxNits / sc_nominalRefWhite;
D2D1_MATRIX_5X4_F rgbtoYnorm = D2D1::Matrix5x4F(
0.2126f / scale, 0, 0, 0,
0.7152f / scale, 0, 0, 0,
0.0722f / scale, 0, 0, 0,
0 , 0, 0, 1,
0 , 0, 0, 0);
// 1st column: [R] output, contains normalized Y (CIEXYZ).
// 2nd column: [G] output, unused.
// 3rd column: [B] output, unused.
// 4th column: [A] output, alpha passthrough.
// We explicitly calculate Y; this deviates from the CEA 861.3 definition of MaxCLL
// which approximates luminance with max(R, G, B).
DX::ThrowIfFailed(histogramMatrix->SetValue(D2D1_COLORMATRIX_PROP_COLOR_MATRIX, rgbtoYnorm));
// 4. Apply a gamma to allocate more histogram bins to lower luminance levels.
ComPtr<ID2D1Effect> histogramGamma;
DX::ThrowIfFailed(
context->CreateEffect(CLSID_D2D1GammaTransfer, &histogramGamma)
);
histogramGamma->SetInputEffect(0, histogramMatrix.Get());
// Gamma function offers an acceptable tradeoff between simplicity and efficient bin allocation.
// A more sophisticated pipeline would use a more perceptually linear function than gamma.
DX::ThrowIfFailed(histogramGamma->SetValue(D2D1_GAMMATRANSFER_PROP_RED_EXPONENT, sc_histGamma));
// All other channels are passthrough.
DX::ThrowIfFailed(histogramGamma->SetValue(D2D1_GAMMATRANSFER_PROP_GREEN_DISABLE, TRUE));
DX::ThrowIfFailed(histogramGamma->SetValue(D2D1_GAMMATRANSFER_PROP_BLUE_DISABLE, TRUE));
DX::ThrowIfFailed(histogramGamma->SetValue(D2D1_GAMMATRANSFER_PROP_ALPHA_DISABLE, TRUE));
// 5. Finally, the histogram itself.
HRESULT hr = context->CreateEffect(CLSID_D2D1Histogram, &m_histogramEffect);
if (hr == D2DERR_INSUFFICIENT_DEVICE_CAPABILITIES)
{
// The GPU doesn't support compute shaders and we can't run histogram on it.
m_isComputeSupported = false;
}
else
{
DX::ThrowIfFailed(hr);
m_isComputeSupported = true;
DX::ThrowIfFailed(m_histogramEffect->SetValue(D2D1_HISTOGRAM_PROP_NUM_BINS, sc_histNumBins));
m_histogramEffect->SetInputEffect(0, histogramGamma.Get());
}
}
// Uses a histogram to compute a modified version of MaxCLL (ST.2086 max content light level).
// Performs Begin/EndDraw on the D2D context.
void D2DAdvancedColorImagesRenderer::ComputeHdrMetadata()
{
// Initialize with a sentinel value.
m_maxCLL = -1.0f;
// MaxCLL is not meaningful for SDR or WCG images.
if ((!m_isComputeSupported) ||
(m_imageInfo.imageKind != AdvancedColorKind::HighDynamicRange))
{
return;
}
// MaxCLL is nominally calculated for the single brightest pixel in a frame.
// But we take a slightly more conservative definition that takes the 99.99th percentile
// to account for extreme outliers in the image.
float maxCLLPercent = 0.9999f;
auto ctx = m_deviceResources->GetD2DDeviceContext();
ctx->BeginDraw();
ctx->DrawImage(m_histogramEffect.Get());
// We ignore D2DERR_RECREATE_TARGET here. This error indicates that the device
// is lost. It will be handled during the next call to Present.
HRESULT hr = ctx->EndDraw();
if (hr != D2DERR_RECREATE_TARGET)
{
DX::ThrowIfFailed(hr);
}
float *histogramData = new float[sc_histNumBins];
DX::ThrowIfFailed(
m_histogramEffect->GetValue(D2D1_HISTOGRAM_PROP_HISTOGRAM_OUTPUT,
reinterpret_cast<BYTE*>(histogramData),
sc_histNumBins * sizeof(float)
)
);
unsigned int maxCLLbin = 0;
float runningSum = 0.0f; // Cumulative sum of values in histogram is 1.0.
for (int i = sc_histNumBins - 1; i >= 0; i--)
{
runningSum += histogramData[i];
maxCLLbin = i;
if (runningSum >= 1.0f - maxCLLPercent)
{
break;
}
}
float binNorm = static_cast<float>(maxCLLbin) / static_cast<float>(sc_histNumBins);
m_maxCLL = powf(binNorm, 1 / sc_histGamma) * sc_histMaxNits;
// Some drivers have a bug where histogram will always return 0. Treat this as unknown.
m_maxCLL = (m_maxCLL == 0.0f) ? -1.0f : m_maxCLL;
}
Schritt 3: Ausführen des HDR-Tonmapping-Vorgangs
Das Tonmapping ist grundsätzlich ein Verlustprozess und kann für eine Reihe von wahrnehmigen oder zielwerten Metriken optimiert werden, sodass es keinen Standardalgorithmus gibt. Windows bietet einen integrierten HDR-Tonmappereffekt als Teil von Direct2D sowie in der Media Foundation HDR-Videowiedergabepipeline. Einige andere häufig verwendete Algorithmen sind ACES Filmic,Ige und ITU-R BT.2390-3 EETF (electrical-electrical transfer function).
Unten sehen Sie einen vereinfachten Farbtonmapperoperator.
// Normally in DirectX, color values are manipulated in shaders on GPU textures.
// This example performs scaling on a CPU color value.
D2D1_VECTOR_4F simpleReinhardTonemapper(
float inputMax, // Content's maximum luminance in scRGB values, e.g. 1.0 = 80 nits.
float outputMax, // Display's maximum luminance in scRGB values, e.g. 1.0 = 80 nits.
D2D1_VECTOR_4F input // scRGB color.
)
{
D2D1_VECTOR_4F output = input;
// Vanilla Reinhard normalizes color values to [0, 1].
// This modification scales to the luminance range of the display.
output.r /= inputMax;
output.g /= inputMax;
output.b /= inputMax;
output.r = (output.r / 1 + output.r);
output.g = (output.g / 1 + output.g);
output.b = (output.b / 1 + output.b);
output.r *= outputMax;
output.g *= outputMax;
output.b *= outputMax;
return output;
}
Erfassen von HDR- und WCG-Inhalten
APIs, die die Angabe von Pixelformaten unterstützen, z. B. die in der Windows. Der Graphics.Capture-Namespace und die IDXGIOutput5::D uplicateOutput1-Methode bieten die Möglichkeit, HDR- und WCG-Inhalte zu erfassen, ohne Pixelinformationen zu verlieren. Beachten Sie, dass nach dem Abrufen von Inhaltsframes zusätzliche Verarbeitung erforderlich ist. Beispiel: HDR-zu-SDR-Tonzuordnung (z. B. KOPIE des SDR-Screenshots für die Internetfreigabe) und Speichern von Inhalten im richtigen Format (z. B. JPEG XR).
Zusätzliche Ressourcen
- Verwenden von HDR Rendering mit dem DirectX Tool Kit für DirectX 11 / DirectX 12. Exemplarische Vorgehensweise zum Hinzufügen von HDR-Unterstützung zu einer DirectX-App mit dem DirectX Tool Kit (DirectXTK).
- Direct2D Advanced Color Images SDK-Beispiel. UWP SDK-Beispiel zur Implementierung eines erweiterten farborientierten HDR- und WCG-Bildviewers mit Direct2D. Veranschaulicht das gesamte Spektrum an bewährten Methoden für UWP-Apps, einschließlich der Reaktion auf Anzeigefunktionsänderungen und der Anpassung an die WHITE-Stufe von SDR.
- Direct3D 12 HDR-Desktopbeispiel. Desktop SDK-Beispiel zur Implementierung einer einfachen Direct3D 12 HDR-Szene.
- Direct3D 12 HDR UWP-Beispiel. UWP-Entsprechung des obigen Beispiels.
- Xbox ATG SimpleHDR PC-Beispiel. Desktop SDK-Beispiel zur Implementierung einer einfachen Direct3D 11 HDR-Szene.