Seite 1 von 1

Failing bei Normalmapping

Verfasst: 25.01.2014, 01:32
von xq
Heyhoh,
ich verzweifle grade an der Normalmapping-Integration in meinen Deferred Renderer.

Mit Normalmapping-Shader:
Bild

Ohne Normalmapping-Shader:
Bild

Die Normalen scheinen irgendwie "völlig" falsch zu sein, aber irgendwie stimmen sie...

So sehen die Normalen im World-Space mit Normalmapping aus:
Bild
Ohne Normalmapping ist es Blau (0.0, 0.0, 1.0)

Also theoretisch sollte das Lighting nicht so verrückt spielen, tut es aber irgendwie.

Shader-Code:
VS:

Code: Alles auswählen

#version 410
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 vertexNormal;
layout(location = 2) in vec2 vertexUV;
layout(location = 4) in vec3 vertexTangent;
layout(location = 5) in vec3 vertexBiTangent;

uniform mat4 World;
uniform mat4 View;
uniform mat4 Projection;

out vec3 position;
out vec3 normal;
out vec3 tangent;
out vec3 bitangent;
out vec2 uv;

void main()
{
	vec4 pos = vec4(vertexPosition, 1);
	gl_Position = Projection * View * World * pos;
	
	position = (World * pos).xyz;

	mat3 mv3x3 = mat3(World);
	normal = normalize(mv3x3 * vertexNormal);
	tangent = normalize(mv3x3 * vertexTangent);
	bitangent = normalize(mv3x3 * vertexBiTangent);

	uv = vertexUV;
}
PS:

Code: Alles auswählen

#version 410

#define WITH_NORMALMAP_UNSIGNED
#define USE_NORMALMAPPING

in vec3 position;
in vec3 normal;
in vec3 tangent;
in vec3 bitangent;
in vec2 uv;

layout(location = 0) out vec4 positionOut;
layout(location = 1) out vec4 normalOut;

uniform sampler2D textureNormalMap;
uniform vec3 viewPosition;
uniform float fBlend;

void main()
{
	positionOut = vec4(position, 1);

	mat3 tm = mat3(tangent, bitangent, normal);

	vec3 bump = normalize(2.0f * texture(textureNormalMap, uv).xyz);
    normalOut.xyz = tm * bump;
	normalOut.xyz = mix(normal, normalOut.xyz, fBlend);
	normalOut.w = 1.0f;
}
Hat irgendwer eine tolle Idee, die mir weiterhelfen könnte?

Grüße
Felix

Re: Failing bei Normalmapping

Verfasst: 25.01.2014, 01:56
von xq
Thread kann geschlossen werden, habe mein Problem gelöst:

Code: Alles auswählen

vec3 bump = normalize(2.0f * texture(textureNormalMap, uv).xyz);
sollte

Code: Alles auswählen

vec3 bump = normalize((255.0f / 127.0f) * texture(textureNormalMap, uv).xyz - (127.0f / 255.0f));
sein.

Grüße, vllt hilft es ja noch dem ein oder anderen,
Felix

Re: Failing bei Normalmapping

Verfasst: 25.01.2014, 13:09
von Artificial Mind
Bist du sicher, dass deine Normalmap auch z von -1 bis 1 enthält?
Bei unseren Normalmaps sind xy von -1 bis 1 und z von 0 bis 1 weil eine Normale die 'nach hinten' zeigt, wenig Sinn ergibt.

Re: Failing bei Normalmapping

Verfasst: 25.01.2014, 13:13
von xq
Ja, ich habe mit Gimp einen Screenshot untersucht. Eine glatte Normalmap hatte den Normalen-Wert von (53, 53, 255) obwohl die Normalmap einen Wert von (128, 128, 255) enthielt.
Heißt, die Umrechnung failt also gar nicht mal bei der Z-Komponente der Normalmap, sondern bei den Farbwerten (Darum auch die "gekippte" Normale über das ganze Bild)

Re: Failing bei Normalmapping

Verfasst: 25.01.2014, 13:56
von xq
Oh ghod what the fuck? Why did this even work?
Ich hatte meine ganzen Texturen als sRGB-Texturen geladen, die waren also alle von Gamma-Space in Linear-Space konvertiert. AUCH die Normalmaps.

Re: Failing bei Normalmapping

Verfasst: 25.01.2014, 14:10
von Artificial Mind
MasterQ32 hat geschrieben:Ja, ich habe mit Gimp einen Screenshot untersucht. Eine glatte Normalmap hatte den Normalen-Wert von (53, 53, 255) obwohl die Normalmap einen Wert von (128, 128, 255) enthielt.
Heißt, die Umrechnung failt also gar nicht mal bei der Z-Komponente der Normalmap, sondern bei den Farbwerten (Darum auch die "gekippte" Normale über das ganze Bild)
(128, 128, 255) wäre in beiden Fällen (0,0,1) Normale.
Die Frage ist, ob die Normale (1,0,0) als (255, 128, 0) oder als (255, 128, 128) gespeichert wird.
Da normalerweise die Normalen nur 'nach vorne' zeigen, kann man ohne Verluste doppelte Genauigkeit der z-Komponente erreichen.

Re: Failing bei Normalmapping

Verfasst: 25.01.2014, 16:45
von Slin
Artificial Mind hat geschrieben: Da normalerweise die Normalen nur 'nach vorne' zeigen, kann man ohne Verluste doppelte Genauigkeit der z-Komponente erreichen.
Hast du mal irgendwie einen Vergleich, der zeigt, dass das tatsächlich eine merkliche Verbesserung bringt? Weil ansonsten find ich eigentlich nur dass es den Shader ein bisschen unleserlicher macht.

Felix,
die Transformation vom 0 - 1 in den -1 - 1 Bereich der Texturwerte brauchst du aber doch trotzdem?

Re: Failing bei Normalmapping

Verfasst: 25.01.2014, 17:10
von Artificial Mind
Slin hat geschrieben: Hast du mal irgendwie einen Vergleich, der zeigt, dass das tatsächlich eine merkliche Verbesserung bringt? Weil ansonsten find ich eigentlich nur dass es den Shader ein bisschen unleserlicher macht.
Einen direkten Vergleich habe ich noch nicht durchgeführt, ist aber ne gute Idee.

Die Frage ist allerdings auch woher man seine Normalmap hat. Eine .jpg Normalmap aus dem Internet ist zwar sehr unterhaltsam, aber auf Dauer nicht geeignet. Selbst die "Normalmaps", die man per GIMP-Plugin erstellt, sind qualitativ minderwertig.
Wenn man das also testet, bräuchte man vernünftige 3D baked Normalmaps.

Re: Failing bei Normalmapping

Verfasst: 25.01.2014, 20:57
von dot
Ein üblicher Trick bei Normalmaps ist es, überhaupt nur zwei Komponenten zu speichern und die dritte im Shader zu rekonstruieren (Pythagoras)... ;)

Re: Failing bei Normalmapping

Verfasst: 25.01.2014, 21:03
von Slin
Tendenziell habe ich aber zu viel vram und viel zu viele Pixel zu rendern ;) Von daher bin ich froh über jede Shaderinstruktion weniger.

Re: Failing bei Normalmapping

Verfasst: 25.01.2014, 21:09
von dot
Es geht nicht nur um den Speicherverbrauch, sondern vor allem um den Bandbreitenbedarf. Und davon hat man rein prinzipiell immer zuviel... ;)

Re: Failing bei Normalmapping

Verfasst: 25.01.2014, 21:26
von Slin
Naja bei meiner mobilen Grafikkarte und 2880*1800 Pixel ist die Bandbreite halt wirklich nicht das Bottleneck und überhaupt war das eher auf der letzten Konsolengeneration und auf Smartphones problematisch als auf aktueller Desktop Hardware.

Re: Failing bei Normalmapping

Verfasst: 25.01.2014, 22:38
von dot
Slin hat geschrieben:Naja bei meiner mobilen Grafikkarte und 2880*1800 Pixel ist die Bandbreite halt wirklich nicht das Bottleneck und überhaupt war das eher auf der letzten Konsolengeneration und auf Smartphones problematisch als auf aktueller Desktop Hardware.
Das kann ich so leider nicht unterschreiben. Klar, wenn man nur ein paar Dreiecke mit einer einzigen Normal Map drauf rendert, dann wird es keinen Unterschied machen. Aber in der Regel ist die Speicherbandbreite fast immer das erste Bottleneck, auf das man stößt, auch auf Desktop Hardware. Außerdem kann ich mit obiger Technik immerhin im selben Speicherplatz (jede GPU wird 24 Bit RGB wohl als 4 Byte pro Pixel behandeln) meine Normalen mit doppelter Genauigkeit (16 Bit pro Kanal) abspeichern... ;)

Re: Failing bei Normalmapping

Verfasst: 26.01.2014, 06:45
von Krishty
Slin hat geschrieben:Tendenziell habe ich aber zu viel vram und viel zu viele Pixel zu rendern ;) Von daher bin ich froh über jede Shaderinstruktion weniger.
Das Verhältnis von Rechengeschwindigkeit zu Speicherlatenz wird immer ungünstiger; darum ist es prinzipiell immer der falsche Weg, etwas über den Speicher zu lösen.

Ich hatte das damals mit meinem Atmospheric Scattering gemacht und bereue es zutiefst: Die GPUs haben ihre ALU-Leistung vervielfacht, aber mein Programm ruckelt heute immernoch so viel wie damals, weil es ununterbrochen auf den Speicher wartet. Andere Leute haben das über Rechenlast gelöst und sind damit heute in dreistelligen Aktualisierungsraten.

Re: Failing bei Normalmapping

Verfasst: 26.01.2014, 14:09
von Krishty
Weil es so gut dazu passt (man beachte die logarithmische Darstellung):
workingset.png
(aus What Every Programmer Should Know About Memory)

Die meisten Probleme heute sind Probleme der Speichermenge, mit der gearbeitet wird. Falls das Working Set in deinen Cache passt, ist dein Programm schnell. Sonst ist es langsam. Erst danach kommt zum Tragen, wie viele Takte deine Berechnungen brauchen (wenn du nicht gerade n mit n^5 vergleichst).

Re: Failing bei Normalmapping

Verfasst: 26.01.2014, 18:01
von Slin
Ihr habt natürlich recht. Ich habe da ohne weiter drüber nachzudenken falsch verallgemeinert. Ich bin auf meiner GPU aktuell ganz klar ALU bound, obwohl ich auf ziemlich viele Daten zugreife. Das liegt aber daran, dass die ALU verdammt viel zu tun hat und meine mobile GPU da eher schwach ist. Auf dem Desktop, vor allem mit neueren GPUs würde das ganze vermutlich wirklich anders aussehen.

Ob es aber generell wirklich Sinn macht die Z-Werte von Tangent Space Normalmaps aus den anderen beiden Werten zu berechnen bezweifle ich irgendwie, genauso wie ich auch eigentlich nicht glaube, dass man da mehr Präzision braucht. Hier ist dann auch einfach die Frage ob der zusätzliche Wert das ganze dann tatsächlich zu groß für den Cache macht, oder ob das nicht eigentlich völlig egal ist ob ich den jetzt habe oder nicht, die Rekonstruktion aber dann vergleichsweise teuer ist.
Wo ich diese Rekonstruktion oft gesehen habe ist bei den Normalen beim Deferred Rendering, wobei es da vorkommen kann, dass die Normale von der Kamera weg zeigt und dann geht es kaputt, von daher sollte man die Normalen dann eher anders encodieren und nicht nur durch weglassen von z.