Failing bei Normalmapping

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
xq
Establishment
Beiträge: 1581
Registriert: 07.10.2012, 14:56
Alter Benutzername: MasterQ32
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

Failing bei Normalmapping

Beitrag 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
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…

Programmiert viel in ⚡️Zig⚡️ und nervt Leute damit.
Benutzeravatar
xq
Establishment
Beiträge: 1581
Registriert: 07.10.2012, 14:56
Alter Benutzername: MasterQ32
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

Re: Failing bei Normalmapping

Beitrag 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
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…

Programmiert viel in ⚡️Zig⚡️ und nervt Leute damit.
Benutzeravatar
Artificial Mind
Establishment
Beiträge: 802
Registriert: 17.12.2007, 17:51
Wohnort: Aachen

Re: Failing bei Normalmapping

Beitrag 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.
Benutzeravatar
xq
Establishment
Beiträge: 1581
Registriert: 07.10.2012, 14:56
Alter Benutzername: MasterQ32
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

Re: Failing bei Normalmapping

Beitrag 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)
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…

Programmiert viel in ⚡️Zig⚡️ und nervt Leute damit.
Benutzeravatar
xq
Establishment
Beiträge: 1581
Registriert: 07.10.2012, 14:56
Alter Benutzername: MasterQ32
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

Re: Failing bei Normalmapping

Beitrag 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.
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…

Programmiert viel in ⚡️Zig⚡️ und nervt Leute damit.
Benutzeravatar
Artificial Mind
Establishment
Beiträge: 802
Registriert: 17.12.2007, 17:51
Wohnort: Aachen

Re: Failing bei Normalmapping

Beitrag 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.
Slin
Beiträge: 44
Registriert: 15.05.2010, 01:21
Echter Name: Nils Daumann
Wohnort: Lübeck
Kontaktdaten:

Re: Failing bei Normalmapping

Beitrag 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?
Benutzeravatar
Artificial Mind
Establishment
Beiträge: 802
Registriert: 17.12.2007, 17:51
Wohnort: Aachen

Re: Failing bei Normalmapping

Beitrag 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.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Failing bei Normalmapping

Beitrag von dot »

Ein üblicher Trick bei Normalmaps ist es, überhaupt nur zwei Komponenten zu speichern und die dritte im Shader zu rekonstruieren (Pythagoras)... ;)
Slin
Beiträge: 44
Registriert: 15.05.2010, 01:21
Echter Name: Nils Daumann
Wohnort: Lübeck
Kontaktdaten:

Re: Failing bei Normalmapping

Beitrag 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.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Failing bei Normalmapping

Beitrag von dot »

Es geht nicht nur um den Speicherverbrauch, sondern vor allem um den Bandbreitenbedarf. Und davon hat man rein prinzipiell immer zuviel... ;)
Slin
Beiträge: 44
Registriert: 15.05.2010, 01:21
Echter Name: Nils Daumann
Wohnort: Lübeck
Kontaktdaten:

Re: Failing bei Normalmapping

Beitrag 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.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Failing bei Normalmapping

Beitrag 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... ;)
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Failing bei Normalmapping

Beitrag 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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Failing bei Normalmapping

Beitrag 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).
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Slin
Beiträge: 44
Registriert: 15.05.2010, 01:21
Echter Name: Nils Daumann
Wohnort: Lübeck
Kontaktdaten:

Re: Failing bei Normalmapping

Beitrag 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.
Antworten