Rekonstruktion der Normale

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Rekonstruktion der Normale

Beitrag von Zudomon »

Es liegt aber tatsächlich daran, dass nicht genug Genauigkeit vorhanden ist. Mit 32 Bit ist es absolut Artefaktfrei... wenn ich 16 Bit nehme, dann ist es annehmbar, wenn ich zum kodieren vorher pow(n.xy, 4) * sign(n.xy) rechne... entsprechendes zum dekodieren (die minimale Anomalie ist aktzeptabel).
Für mich ist das eine eindeutig. Aber ich vermute mal, dass das genau das richtige Thema für dich (Krishty) ist :D, wo du, falls es die Zeit nun zulässt, analysierst, was da Sache ist. Falls du dem auf den Grund gehst, bin ich gespannt, ob meine Vermutung richtig ist. Ich denke mal, dass gerade das sqrt dafür verantwortlich ist. Es streckt einen Bereich (welchen weiß ich jetzt nicht), wie wenn man eine Lupe drauf hält und dadurch ist die Genauigkeit an der Stelle nicht mehr hoch genug.
Benutzeravatar
unbird
Beiträge: 9
Registriert: 17.12.2015, 08:35

Re: Rekonstruktion der Normale

Beitrag von unbird »

Ich vermute mal das Problem rührt daher, dass Du zuerst über 8 bit gehst. Mit der 0.5*n+0.5 Kodierung kann man die 0 nicht exakt darstellen:

0.5 * 0 + 0.5 = 0.5, -> *255 = 127.5, also 127 oder 128 nach rundern, ergo 0.5 daneben. Recht viel.

Volle float-Texture oder diese ^4 Kodierung verstecken das Problem nur. Schreib besser mal erst Deine Shader auf deferred um und versuch dann nochmals 16F (oder noch besser NICHT float, denn der half-float verschenkt nämlich auch bits). Zudem hat D3D9 die Einschränkung bei multi-Render-Targets, dass alle Formate gleich dick sein müssen (Bit-Anzahl). All Deine GBuffer-Texturen auf 128 bit und Deine Bandbreite explodiert.
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Rekonstruktion der Normale

Beitrag von Zudomon »

unbird hat geschrieben:Ich vermute mal das Problem rührt daher, dass Du zuerst über 8 bit gehst.
Das kann nicht sein, weil es ausschließlich im Shader passiert. Also im Shader hab ich ja sowas wie (n*0.5+0.5)*2-1. Deine Vermutung würde stimmen, wenn man den Wert zwischendurch in eine 8-Bit Textur legen würde.
unbird hat geschrieben:Zudem hat D3D9 die Einschränkung bei multi-Render-Targets, dass alle Formate gleich dick sein müssen (Bit-Anzahl).
Ich glaube, das ist nicht so. Wobei das hier Herstellerabhängig war. Kann aber nicht mehr sagen, in welcher Präsentation ich das gelesen hatte. Allerdings weiß ich noch, dass ATI so langsam wird, wie das größte RT-Format, bei NVidia ist das nicht so. Demnach ist klar, dass man selbst entscheiden kann, welche Formate man bei MRT rein gibt. Allerdings müssen sie die gleiche Breite und Höhe haben.
unbird hat geschrieben: (oder noch besser NICHT float, denn der half-float verschenkt nämlich auch bits)
Also XYZ Normalen, 8 Bit ist aber ein Himmelweiter Unterschied zu 16 Bit - Float. Wenn gewünscht, kann ich gerne mal ein Vergleichsbild machen.


Vielleicht könnte man, um das Artefakt besser zu vermeiden, vielleicht noch wie beim triplanar Mapping die größte Komponente Suchen und dann in X, Y oder Z Richtung aufteilen, statt immer nur Z zu nutzen und somit das Artefakt bei Z ~ 0 zu bekommen. Allerdings vermute ich, dass sowas mehr Instruktions benötigt als das, was ich jetzt mache. Das sign() braucht zwar ne ganze Menge Instruktionen, das habe ich aber schon durch ein step(0, n)*2-1 ersetzt, welches hier meine Anforderungen auch besser abdeckt, da sign(0) auch 0 zurückliefert, was tötlich ist, wenn ich die Z-Komponente als Depth Wert verwende. Heißt nämlich, dass mein Depth Wert 0 annehmen würde, wenn n.z = 0 wäre.
Antworten