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

13.05.2021, 22:19

Transformieren von Normalenvektoren

Hallo zusammen,

ich habe ein eventuell simples aber dennoch sehr seltsames Problem mit DirectX11.
Ich möchte die Normalen eines 3D Meshes transformieren, damit ich im Pixelshader die Beleuchtung berechnen kann. Eigentlich muss man dafür ja die transponierte inverse der Weltmatrix nutzen. Nun habe ich folgendes seltsames Phänomen:

Die Szenerie sieht exakt gleich aus, wenn ich die Normalen mittels der Weltmatrix oder der Transponierten Inversen transformiere. Ich nutze eigentlich eine eigene Math lib (aus dem ersten Teil von Foundations of Game Engine Development) habe jedoch zu Testzwecken die DirectXMath lib verwendet.

Code mit transponierter inverser

C-/C++-Quelltext

1
2
3
4
5
mWorld = TranslationMatrix(entity.pos) * RotationYMatrix(entity.rotation.y);
    Matrix4 camMatrix = mCam->GetMatrix();
    mPerObject.WVP = Transpose(mWorld) * camMatrix;
    mPerObject.World = DirectX::XMMatrixInverse(nullptr, DirectX::XMMatrixTranslation(0, 0, 0) * DirectX::XMMatrixRotationY(TO_RAD(entity.rotation.y)));//Transpose(mWorld);
    mPerObject.WorldInvTranspose = Transpose(Inverse(mWorld));


Code mit normaler Weltmatrix (da der Shader column-major arbeitet muss ich hier ja noch einmal transponieren)

C-/C++-Quelltext

1
2
3
4
5
mWorld = TranslationMatrix(entity.pos) * RotationYMatrix(entity.rotation.y);
    Matrix4 camMatrix = mCam->GetMatrix();
    mPerObject.WVP = Transpose(mWorld) * camMatrix;
    mPerObject.World = DirectX::XMMatrixTranspose(DirectX::XMMatrixTranslation(0, 0, 0) * DirectX::XMMatrixRotationY(TO_RAD(entity.rotation.y)));//Transpose(mWorld);
    mPerObject.WorldInvTranspose = Transpose(Inverse(mWorld));


VertexShader (PixelShader nutzt die Normalenvektoren ohne Veränderung)

HLSL-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
VS_OUTPUT VS(float4 inPos : POSITION, float3 normal : NORMAL, float2 tex : TEXCOORD)
{
    VS_OUTPUT output;

    output.Pos = mul(inPos, WVP);
    output.WPos = mul(inPos, World);
    output.Normal = mul(normal, World);
    
    
    output.Normal = normalize(output.Normal);
    output.Tex = tex;

    return output;
}


Rendering mit Inverser


Rendering mit Weltmatrix


Ich hoffe mir kann jemand einen Anstoß geben was hier genau schief läuft :D

Viele Grüße,
Soaring
»Soaring« hat folgende Bilder angehängt:
  • inv_pers.PNG
  • trans.PNG

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

14.05.2021, 09:16

Da läuft nichts schief. Es gibt nur dann einen Unterschied zwischen den beiden Vorgehensweisen, wenn du eine nicht-uniforme Skalierung in deiner Transformation drin hast - also eine Skalierung, die nicht auf allen Achsen gleich ist. Siehe auch: https://stackoverflow.com/questions/1365…-modelview-matr. Wenn du garantieren kannst, dass das nicht der Fall ist, dann kannst du ganz normal mit der Weltmatrix transformieren. Ansonsten, wenn du irgendeine Art von Skalierung drin hast, müsstest du auch die resultierende Normale nochmal normalisieren, denn eine Skalierung kann die Länge der Normale ändern, was bei der Beleuchtung einen Einfluss hätte.

3

15.05.2021, 20:21

Ich verstehe, dann ergibt das Sinn. Ich hatte noch eine Implementierungsfehler in der Mathe Lib, weswegen ich nicht sicher war, ob das Ergebnis jetzt von der Implementierung oder der Mathematik selbst kommt :D

Werbeanzeige