Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

18.05.2017, 17:40

Normalen transformieren

Hallo,

ich möchte die Normalen korrekt transformieren, wenn ich eine Landschaft beliebig skaliere.
Was ich bisher dazu gefunden habe, ist, dass man die inverse Matrix des Modells transponieren und mit der nicht transformierten Normalen multiplizieren muss.
Die Umrechnung der Normalen findet bei mir im Vertex-Shader statt:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...

layout(location=1) in vec4 VertexNormal;

...

uniform mat4 ModelNormalMat;

...

out vec3 Normal;

...

void main()
{

     ...

     Normal = (ModelNormalMat * VertexNormal).xyz; 

     ...

}


ModelNormalMat wird CPU-seitig übergeben:

Quellcode

1
modelMatrix.invert().transpose()


Leider hat das keinerlei Auswirkung auf die Normalen. Sie bleiben unverändert. Dies scheint wohl mit der Orthogonalität der Matrix zusammenzuhängen.
Die Frage ist nun: Wie kann ich das korrekt realisieren?

SlinDev

Treue Seele

Beiträge: 142

Wohnort: Lübeck

Beruf: Programmierer

  • Private Nachricht senden

2

18.05.2017, 17:51

Was erwartest du denn als Ergebnis?
Die Normalen beschreiben ja nur die Richtung in die deine Oberfläche zeigt. Dabei ist die Skalierung und Translation deines Meshes völlig egal und nur die Rotation ist wichtig.
Entsprechend brauchst du um Shader eigentlich nur eine Rotationsmatrix für die Normalen. Du kannst aber auch die modelMatrix nehmen, die Translation wegschmeißen und die normalen normalisieren.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

3

18.05.2017, 17:51

Also erstmal brauchst du keine 4x4-Matrix für die Normalen, denn dort findet keine Translation statt. Es reicht, wenn du nur die linke obere 3x3-Teilmatrix invertierst und transponierst und die Vertexnormale (dann vec3 statt vec4) auch nur mit dieser 3x3-Matrix multiplizierst. Außerdem solltest du den Normalenvektor nach der Transformation im Shader wieder normieren, sonst wirst du falsche Ergebnisse bei der Beleuchtung bekommen, wenn du eine Skalierung drin hast.

Was exakt meinst du mit "keinerlei Auswirkung auf die Normalen"? Dasselbe Ergebnis wie wenn du die Normale ohne jegliche Transformation übernehmen würdest?

Ah, SlinDev war ein Fünkchen schneller :)

4

18.05.2017, 18:14

Schon einmal danke für die schnellen Antworten!
Eine Rotation des Modells findet nicht statt. Nur eine Skalierung in X-, Y- und Z-Richtung.

Was ich mit keinerlei Auswirkung meine:

Wenn ich die Landschaft von der Höhe her z. B. so skaliere, dass alle Vertices auf einer Höhe sind, sind die Schattierungen immer noch vorhanden.
So eine Art Pseudo-3D. Dies darf nicht sein. Die Normalen müssten in diesem Fall ja nach oben zeigen.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

5

18.05.2017, 18:53

Du meinst eine Matrix, die auf der y-Achse (wenn die nach oben zeigt) eine Skalierung von Null durchführt?
Eine solche Matrix ist nicht invertierbar. Versuch's stattdessen mal mit einem sehr kleinen Skalierungswert (wie 0.0001).

6

18.05.2017, 19:07

Oder sonst einfach alle Normalen durchgehen und die Y-Achse manuell auf 0 setzen.
Albert Einstein sagte: "2 Stunden mit einem netten Mädchen fühlen sich an wie 20 Minuten, 20 Minuten auf einem heißen Ofen fühlen sich an wie 2 Stunden. - Das ist Relativität"

7

19.05.2017, 00:23

Die Normalen müssten sich doch immer mehr dem Up-Vektor angleichen, je niedriger die Y-Koordinate skaliert wird. Oder sehe ich das falsch?
Nochmal zur Info: Die Skalierung der Achsen ist unabhängig möglich. D. h., es kann auch z. B. nur in Y-Richtung skaliert werden.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Starcluster« (19.05.2017, 00:37)


David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

8

19.05.2017, 01:03

Ja, ich denke das stimmt. Hast du meinen Hinweis mit y-Skalierung = 0 beachtet?

9

19.05.2017, 16:30

Konnte das Problem lösen.
Hatte nicht daran gedacht, zur Berechnung der Normalenmatrix nur den Diagonalanteil in Betracht zu ziehen:

Quellcode

1
2
3
4
vec3 c1 = vec3(1.0f / Scaling.x, 0.0f, 0.0f);
vec3 c2 = vec3(0.0f, 1.0f / Scaling.y, 0.0f);
vec3 c3 = vec3(0.0f, 0.0f, 1.0f / Scaling.z);
mat3 normalMat = mat3(c1, c2, c3);


Damit funktioniert es nun einwandfrei.

Werbeanzeige