Ich sehe, dass die Funktionen ddx
und ddy
glsl und die hlsl-Entsprechungen von Zeit zu Zeit im Shader-Code auftauchen. Ich verwende sie derzeit, um Bump-Mapping ohne Tangens oder Bitangens durchzuführen, aber ich habe den Code im Grunde genommen kopiert und eingefügt. Ich verstehe nicht, was diese Funktionen tatsächlich sind, was sie tun und wann ich sie verwenden möchte.
Also Fragen:
- Was sind die Funktionen der Bildschirmbereichsableitungen?
- Was machen diese Funktionen? Die Eingabewerte und Ausgabewerte
- Für welche Effekte werden sie am häufigsten verwendet?
- Welche Art von Effekten erfordern, dass Sie sich mit diesen Funktionen befassen?
Antworten:
Erstens ist es hilfreich zu wissen, dass GPUs immer Fragment- / Pixel-Shader auf 2x2 Pixelblöcken gleichzeitig auswerten. (Auch wenn letztendlich nur einige dieser Pixel gezeichnet werden müssen, während andere außerhalb des Polygons liegen oder verdeckt sind - die nicht benötigten Fragmente werden ausgeblendet, anstatt am Ende geschrieben zu werden.)
Die Bildschirmbereichsableitung einer Variablen (oder eines Ausdrucks)
v
in Ihrem Shader ist die Differenz im Wert vonv
(an diesem Punkt im Code) von einer Seite dieses 2x2-Pixel-Quad zur anderen. dh.ddx
ist der Wert vonv
im rechten Pixel minus dem Wert vonv
im linken Pixel und ähnlich fürddy
die Vertikale.Dies antwortet: "Wie schnell nimmt
v
zu oder ab, wenn wir uns horizontal (ddx) oder vertikal (ddy) über den Bildschirm bewegen?" - dh. In Bezug auf die Berechnung approximiert es die partiellen Ableitungen Ihrer Variablen (ungefähr, weil bei jedem Fragment diskrete Stichproben verwendet werden, anstatt das infinitesimale Verhalten der Funktion mathematisch zu bewerten).Für skalare Größen können wir dies auch als einen Gradientenvektor betrachten,
∇v = float2(ddx(v), ddy(v))
der entlang der Bildschirmbereichsrichtung zeigt, in der erv
am schnellsten zunimmt.Diese Art von Informationen wird häufig intern verwendet, um eine geeignete Mipmap oder einen anisotropen Filterkern für Textur-Lookups auszuwählen . Wenn meine Kamera beispielsweise fast parallel zur vertikalen
uv
Richtung einer strukturierten Bodenebene aussieht , istddy(uv.y)
sie im Vergleich zu sehr großddx(uv.x)
(da die vertikale Achse auf dem Bildschirm verkürzt ist - ein Pixelschritt deckt vertikal einen längeren Abschnitt des Texturraums ab) teilt der Textur-Sampling-Hardware mit, dass ich eine anisotrope Filterung benötige, um die vertikale Texturrichtung stärker als die horizontale zu verwischen, um Aliasing-Artefakte zu vermeiden.Für die meisten einfachen Effekte müssen Sie diese Ableitungen nicht verwenden, da die grundlegenden 2D-Texturabtastmethoden dies für Sie erledigen. Wie Le Comte du Merde-fou in einem Kommentar oben erwähnt, müssen Sie beim Verzerren Ihrer Textur-Lookups möglicherweise die zu verwendenden Screenspace-Derivate manuell abrufen und / oder massieren, um die Hardware bei der Auswahl der geeigneten Filterung zu unterstützen (z. B. via
tex2Dlod
in HLSL)Bildschirmabziehbilder sind ein solcher Fall, bei dem ein einzelner 2x2-Block eine große Sprungdiskontinuität in der berechneten Texturkoordinate abdecken kann, was zu einer verschmierten oder aliasierten Kante führt, wenn Sie das System den Filterpegel naiv berechnen lassen. Dieser Artikel geht detailliert auf dieses Artefakt ein und versucht, es zu mildern .
Diese Ableitungen können auch nützlich sein, wenn Sie Rauschfunktionen bei der Erzeugung prozeduraler Texturen verwenden. Wenn Sie beispielsweise prozedurales Rauschen in eine normale Karte umwandeln möchten, geben ddx & ddy eine einfache, wenn auch ungefähre Methode, um zu berechnen, wie sich der Rauschwert in der Nähe des aktuellen Fragments ändert und in welche Richtung er abfällt kann eine entsprechende Normalen konstruieren.
Techniken zum Rendern von Antialias-Linien oder Schnittpunkten können auch Bildschirmbereichsableitungen verwenden, um sicherzustellen, dass die Dicke / der Abfall konsistent ist und nicht von der Geometrie oder dem Betrachtungswinkel abhängt.
In diesem Vortrag über Sand-Rendering in Journey erwähnt der Redner, dass sie diese abgeleiteten Funktionen hätten verwenden können, um zu steuern, wie funkelnd der Sand entlang flüchtiger Kanten ist ... wenn sie zu diesem Zeitpunkt davon gewusst hätten (stattdessen verwendeten sie einen Mipmapping-Trick) die unter der Haube sowieso von solchen Derivaten angetrieben wird)
Ein letzter Hinweis: Bildschirmbereichsableitungen können mit "grober" / geringer Genauigkeit (dh ein Paar von Ableitungen wird vom gesamten Quad geteilt) oder "fein" / hoher Genauigkeit (dh jedes Pixel wird nur mit seiner unmittelbaren verglichen) berechnet werden Nachbarn im Quad, die vier verschiedene Ableitungspaare über dem Quad ergeben könnten). Grob ist im Allgemeinen ausreichend, aber wenn Sie feststellen, dass in Ihrem Effekt 2x2 Blöcke sichtbar sind, ist dies ein guter Hinweis, den Sie auf Fein / Hochpräzision umstellen möchten. ;)
(In der Abbildung oben habe ich Berechnungen für feine Ableitungen verwendet, aber Vorsicht, dass nur ddx / ddy für sich genommen standardmäßig grobe Ableitungen verwenden kann.)
quelle
v
hier), und da es sich um ein 2x2-Quad handelt, gibt es keine Pixel dazwischen. Wenn wir also das obere linke Fragment des Quad schattieren und dort v = 1 und im oberen rechten Fragment v = 4, dann ist ddx (v) = 3 (mit der Aussage "v erhöht sich um 3, wenn wir uns bewegen) von links nach rechts ")