OpenGL Specular Shading - Probleme mit Gradientenstreifen

8

Ich benutze Phong Shading als mein Beleuchtungsmodell. Trotzdem erzeugt die Spiegelschattierung Gradienten im Lichtkegel:

Geben Sie hier die Bildbeschreibung ein

Hoffentlich können Sie sehen, dass sich der Gradient von der unteren linken Ecke entlang des Quaders ausdehnt.

Hier ist der Shader-Code, der dieses spiegelnde Licht erzeugt:

vec3 viewDir = normalize(-FragPos);
vec3 lightDir = normalize(-light.direction);
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);

Übrigens mache ich meine Beleuchtungsberechnungen im Sichtraum.

Gibt es eine Chance, die Beleuchtung sanfter zu machen?

enne87
quelle
Wenn Sie "Farbverläufe" sagen, meinen Sie damit sichtbare Diskontinuitäten in der Farbe? Ich gehe davon aus, dass Sie keine flache Farbe wollen, sondern einen glatten Farbverlauf ohne sichtbare Bänder?
Trichoplax
Genau das will ich.
enne87
Übergeben Sie, dass lightDir in diesem Fall im Ansichtsbereich ist?
Daniel Tran
Ja, ich beleuchte im Sichtraum.
enne87

Antworten:

8

Dies ist ein häufiges Problem bei sehr subtilen Verläufen. Das Problem ist, dass das Bild mit 8 Bit pro Komponente angezeigt wird und dies nicht genau genug ist, um unter diesen Bedingungen einen für das Auge glatten Farbverlauf zu erzielen.

Die zugrunde liegenden Berechnungen, die im Shader durchgeführt werden, sind jedoch präziser (z. B. float = 24 effektive Mantissenbits), sodass Sie Dithering anwenden können, um das Erscheinungsbild des Bildes zu verbessern.

Sie können dies tun, indem Sie dem Wert jedes Pixels im Shader etwas zufälliges Rauschen hinzufügen. Das Rauschen kann von einer Textur stammen, die mit zufälligen Graustufenwerten in [0, 1] gefüllt und 1: 1 auf Bildschirmpixel abgebildet wird. Im Shader ordnen Sie dies dem Bereich [−0.5 / 255, 0.5 / 255] neu zu und fügen ihn der Ausgabefarbe hinzu.

Hier ist ein Shadertoy, der dies demonstriert. Die linke Seite hat kein Zittern; Die rechte Seite verwendet das gerade beschriebene Verfahren. Wie Sie sehen können, verschwindet die Streifenbildung rechts.

Streifen links;  rechts schwankte

Durch Dithering können Sie effektiv Zwischenwerte zwischen 8-Bit-Integer-Ebenen darstellen. Beispielsweise wird ein Bereich, den der Shader als 82,3 (von 255) berechnet, normalerweise gleichmäßig auf 82 abgerundet. Beim Dithering wird er jedoch als zufällige Mischung ausgegeben, wobei 70% der Pixel auf 82 und 30% eingestellt sind bis 83. Das Auge mittelt über dieses sehr leichte, hochfrequente Rauschen und es wird praktisch unsichtbar.

Nathan Reed
quelle
Guter Trick. Mir ist aufgefallen, dass Sie den Pixelkoordinaten im Shadertoy 0,5 hinzufügen. Ist dies eher ein Treffer für Pixelzentren in der Textur als für lerped-Samples?
Russ
2
@russ Hmm, ich habe das Bit tatsächlich von einem anderen Shadertoy kopiert. : D Auf den zweiten Blick denke ich, dass .5 eigentlich nicht benötigt wird; fragCoordsollte bereits auf Pixelzentren sein.
Nathan Reed
3
Für alle Interessierten gibt es hier auch einen gut beschriebenen Artikel zum Implementieren von Dithering, um Farbstreifen zu vermeiden. Viel Spaß beim Codieren!
enne87
Sie können versuchen, eine tatsächliche statistische Fehlerverteilung durchzuführen, anstatt nur gleichmäßig Rauschen hinzuzufügen, um ein noch besseres Ergebnis zu erzielen. tannerhelland.com/4660/dithering-eleven-algorithms-source-code
v.oddou
@ v.oddou Vielleicht. Ich denke, die Fehlerverbreitung würde einen zusätzlichen Vollbilddurchlauf erfordern, anstatt Rauschen hinzuzufügen, das in einem Shader inline erfolgen kann.
Nathan Reed