Präzisions- und numerische Beschneidung in Effektdiagrammen

Anwendungen, die Effekte mit Direct2D rendern, müssen darauf achten, das gewünschte Maß an Qualität und Vorhersagbarkeit in Bezug auf die numerische Genauigkeit zu erreichen. In diesem Thema werden bewährte Methoden und relevante Einstellungen in Direct2D beschrieben, die in den

  • Ihr Effektdiagramm basiert auf hoher numerischer Genauigkeit oder Farben außerhalb des [ Bereichs 0, 1, und Sie möchten sicherstellen, dass diese immer ] verfügbar sind.
  • Oder Ihr Effektdiagramm basiert auf der Renderingimplementierung, um Zwischenfarben an den Bereich 0, 1 zu klammern, und Sie möchten sicherstellen, dass diese Klammer immer [ ] auftritt.

Direct2D unterteilt ein Effektdiagramm häufig in Abschnitte und rendert jeden Abschnitt in einem separaten Schritt. Die Ausgabe einiger Schritte kann in Direct3D-Zwischentexturen gespeichert werden, die standardmäßig einen begrenzten numerischen Bereich und eine begrenzte Genauigkeit aufweisen. Direct2D garantiert nicht, ob oder wo diese Zwischentexturen verwendet werden. Dieses Verhalten kann je nach GPU-Funktionen sowie zwischen den Windows variieren.

In Windows 10 verwendet Direct2D aufgrund der Verwendung der Shaderverknüpfung weniger Zwischentexturen. Direct2D erzeugt daher möglicherweise andere Ergebnisse mit Standardeinstellungen als in vorherigen Windows Releases. Dies wirkt sich hauptsächlich auf Szenarien aus, in denen Shaderverknüpfungen in einem Effektdiagramm möglich sind und dieses Diagramm auch Effekte enthält, die Ausgabefarben für erweiterten Bereich erzeugen.

Übersicht über Effektrendering und Zwischenergebnisse

Zum Rendern eines Effektdiagramms sucht Direct2D zuerst das zugrunde liegende Diagramm von "Transformationen", wobei eine Transformation ein in einem Effekt verwendeter Graphknoten ist. Es gibt verschiedene Arten von Transformationen, einschließlich derer, die Direct3D-Shader zur Verwendung durch Direct2D bereitstellen.

Beispielsweise kann Direct2D ein Effektdiagramm wie folgt rendern:

Effektdiagramm mit Zwischentexturen

Direct2D sucht nach Möglichkeiten, die Anzahl der Zwischentexturen zu reduzieren, die zum Rendern des Effektdiagramms verwendet werden. diese Logik ist für Anwendungen nicht transparent. Beispielsweise kann das folgende Diagramm von Direct2D mit einem Direct3D-Zeichnen-Aufruf und ohne Zwischentextur gerendert werden:

Effektdiagramm ohne Zwischentexturen

Vor der Windows 10 verwendet Direct2D immer Zwischentexturen, wenn innerhalb desselben Effektdiagramms Shader mit mehreren Pixeln verwendet wurden. Die meisten integrierten Effekte, die einfach Farbwerte anpassen (z. B. Helligkeit oder Sättigung), verwenden Pixel-Shader.

In Windows 10 kann Direct2D jetzt die Verwendung von Zwischentexturen in solchen Fällen vermeiden. Hierzu werden angrenzende Pixel-Shader intern miteinander verlinkt. Zum Beispiel:

Windows 10-Effektdiagramm mit mehreren Pixel-Shadern und ohne Zwischentexturen

Beachten Sie, dass nicht alle angrenzenden Pixel-Shader in einem Diagramm miteinander verknüpft werden können, und daher nur bestimmte Diagramme unterschiedliche Ausgaben für Windows 10. Ausführliche Informationen finden Sie unter Effect Shader Linking. Die wichtigsten Einschränkungen sind:

  • Ein Effekt wird nicht mit Effekten verknüpft, die seine Ausgabe verbrauchen, wenn der erste Effekt als Eingabe für mehrere Effekte verbunden ist.
  • Ein Effekt wird nicht mit einem Effekt verknüpft, der als Eingabe festgelegt ist, wenn der erste Effekt seine Eingabe an einer anderen logischen Position als die Ausgabe abwertet. Beispielsweise kann ein Color Matrix-Effekt mit seiner Eingabe verknüpft sein, aber ein Convolution-Effekt ist nicht.

Integriertes Effektverhalten

Viele integrierte Effekte erzeugen möglicherweise Farben außerhalb des [ Bereichs 0, 1 im nichtpremultipliierten Farbraum, auch wenn ihre Eingabefarben innerhalb dieses ] Bereichs liegen. In diesem Fall können solche Farben numerischen Beschneidungsausschnitten unterliegen. Beachten Sie, dass es wichtig ist, den Farbbereich in einem nicht multipliierten Raum zu berücksichtigen, obwohl integrierte Effekte in der Regel Farben im prämultipliierten Raum erzeugen. Dadurch wird sichergestellt, dass die Farben innerhalb des Bereichs bleiben, auch wenn sie von anderen Effekten später nicht mehr verwendet werden.

Einige der Effekte, die diese Farben mit nicht dem Bereich entfernten Bereich aus geben können, bieten eine "ClampOutput"-Eigenschaft. Dazu zählen unter anderem folgende Einstellungen:

Wenn Sie die Eigenschaft "ClampOutput" für diese Effekte auf TRUE festlegen, wird sichergestellt, dass unabhängig von Faktoren wie Shaderverknüpfungen ein konsistentes Ergebnis erzielt wird. Beachten Sie, dass die Klammer im nicht multipliierten Raum auftritt.

Andere integrierte Effekte können auch Ausgabefarben erzeugen, die über den Bereich 0, 1 in einem nichtpremultipliierten Raum hinausgehen, auch wenn ihre Farbpixel [ (und die "Color"-Eigenschaften, falls verfügbar) innerhalb dieses Bereichs ] liegen. Dazu zählen unter anderem folgende Einstellungen:

Erzwingen der numerischen Beschneidung in einem Effektdiagramm

Wenn oben aufgeführte Effekte verwendet werden, die keine "ClampOutput"-Eigenschaft haben, sollten Anwendungen erwägen, numerisches Klammern zu erzwingen. Dies kann durch Einfügen eines zusätzlichen Effekts in das Diagramm erfolgen, das seine Pixel klammert. Es kann ein Color Matrix-Effekt verwendet werden, dessen "ClampOutput"-Eigenschaft auf TRUE festgelegt ist und die ColorMatrix-Eigenschaft als Standardwert (Pass-Through) belässt.

Eine zweite Möglichkeit, konsistente Ergebnisse zu erzielen, besteht in der Anforderung, dass Direct2D Zwischentexturen mit höherer Genauigkeit verwendet. Dies wird im Folgenden beschrieben.

Steuern der Genauigkeit von Zwischentexturen

Direct2D bietet einige Möglichkeiten, die Genauigkeit eines Graphen zu steuern. Vor der Verwendung von Formaten mit hoher Genauigkeit in Direct2D müssen Anwendungen sicherstellen, dass sie von der GPU ausreichend unterstützt werden. Verwenden Sie id2D1DeviceContext::IsBufferPrecisionSupported,um dies zu überprüfen.

Anwendungen können mithilfe von WARP (Software Emulation) ein Direct3D-Gerät erstellen, um zu gewährleisten, dass alle Puffergenauigkeiten unabhängig von der tatsächlichen GPU-Hardware auf dem Gerät unterstützt werden. Dies wird in Szenarien wie dem Anwenden von Effekten auf ein Foto beim Speichern auf dem Datenträger empfohlen. Auch wenn Direct2D Pufferformate mit hoher Genauigkeit auf der GPU unterstützt, wird die Verwendung von WARP in diesem Szenario auf GPUs auf Featureebene 9.X empfohlen, da die Genauigkeit der Shaderarithmetik und der Stichprobenentnahme auf einigen mobilen GPUs mit geringer Leistung eingeschränkt ist.

In jedem der folgenden Fälle ist die angeforderte Genauigkeit tatsächlich die minimale Genauigkeit, die Direct2D verwendet. Wenn keine Zwischenergebnisse erforderlich sind, kann eine höhere Genauigkeit verwendet werden. Direct2D kann auch Zwischentexturen für verschiedene Teile desselben Graphen oder für andere Diagramme vollständig freigeben. In diesem Fall verwendet Direct2D die maximale Genauigkeit, die für alle beteiligten Vorgänge angefordert wird.

Genauigkeitsauswahl von ID2D1DeviceContext::SetRenderingControls

Die einfachste Möglichkeit, die Genauigkeit der Zwischentexturen von Direct2D zu steuern, ist die Verwendung von ID2D1DeviceContext::SetRenderingControls. Dies steuert die Genauigkeit aller Zwischentexturen, solange eine Genauigkeit nicht auch manuell für Effekte oder Transformationen direkt festgelegt wird.

if (Device->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
  // Get the current rendering controls
  D2D1_RENDERING_CONTROLS renderingControls = {};
  Context->GetRenderingControls(&renderingControls);

  // Switch the precision within the rendering controls and set it
  renderingControls.bufferPrecision = D2D1_BUFFER_PRECISION_32BPC_FLOAT;
  Context->SetRenderingControls(&renderingControls);
}
              

Genauigkeitsauswahl aus Eingaben und Renderzielen

Anwendungen können sich auch auf die Genauigkeit der Eingaben in ein Effektdiagramm verlassen, um die Genauigkeit von Zwischentexturen zu steuern. Dies gilt, solange eine Puffergenauigkeit nicht mit ID2D1DeviceContext::SetRenderingControlsangegeben wird und nicht manuell für Effekte und direkte Transformationen festgelegt wird.

Die Genauigkeit der Eingaben für Effekte wird über das Diagramm propagiert, um die Genauigkeit von Downstream-Zwischenprodukten auszuwählen. Wenn verschiedene Verzweigungen im Effektdiagramm aufeinander treffen, wird die höchste Genauigkeit aller Eingaben verwendet.

Die auf der Grundlage einer Direct2D-Bitmap ausgewählte Genauigkeit wird anhand ihres Pixelformats bestimmt. Die für eine ID2D1ImageSource ausgewählte Genauigkeit wird anhand des WIC-Pixelformats der zugrunde liegenden IWICBitmapSource bestimmt, die zum Erstellen von ID2D1ImageSource verwendet wird. Beachten Sie, dass Direct2D das Erstellen von Bildquellen mit WIC-Quellen nicht mithilfe von Genauigkeiten zulässt, die von Direct2D und der GPU nicht unterstützt werden.

Es ist möglich, dass Direct2D einem Effekt basierend auf seinen Eingaben keine Genauigkeit zuweisen kann. Dies geschieht, wenn ein Effekt keine Eingaben hat oder wenn eine ID2D1CommandList verwendet wird, die keine bestimmte Genauigkeit auftrat. In diesem Fall wird die Genauigkeit von Zwischentexturen anhand der Bitmap festgelegt, die als aktuelles Renderziel des Kontexts festgelegt ist.

Genauigkeitsauswahl direkt für den Effekt und die Transformationen

Die minimale Genauigkeit für Zwischentexturen kann auch an expliziten Positionen in einem Effektdiagramm festgelegt werden. Dies wird nur für erweiterte Szenarien empfohlen.

Die minimale Genauigkeit kann mithilfe einer -Eigenschaft für einen Effekt wie folgt festgelegt werden:

if (Device->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
  hr = Effect->SetValue(D2D1_PROPERTY_PRECISION, D2D1_BUFFER_PRECISION_32BPC_FLOAT);
}
              

Innerhalb einer Effektimplementierung kann die minimale Genauigkeit mit ID2D1RenderInfo::SetOutputPrecision wie folgt festgelegt werden:

if (EffectContext->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
  hr = RenderInfo->SetOutputBuffer(
  D2D1_BUFFER_PRECISION_32BPC_FLOAT,
  D2D1_CHANNEL_DEPTH_4);
}
              

Beachten Sie, dass die für einen Effekt festgelegte Genauigkeit an Downstreameffekte im gleichen Effektdiagramm weiterverfolgen wird, es sei denn, für diese Downstreameffekte wird eine andere Genauigkeit festgelegt. Die für eine Transformation innerhalb eines Effekts festgelegte Genauigkeit wirkt sich nicht auf die Genauigkeit für Downstreamtransformationsknoten aus.

Im Folgenden finden Sie die vollständige rekursive Logik, die verwendet wird, um die minimale Genauigkeit für einen Zwischenpuffer zu bestimmen, der die Ausgabe eines bestimmten Transformationsknotens speichert:

Logik für minimale Genauigkeit des Zwischenpuffers