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

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

1

13.11.2010, 16:55

[HLSL] Probleme bei Normalmapping

Hi Leute!
Ich habe ein Problem mit meinem Normalmapping-Shader: Die Normalen sind nicht richtig.
Ich "versuche" die Normalen der Normalmap in den WorldSpace zu transformieren und damit dann die Beleuchtung zu berechnen.
Hier der HLSL Code:

HLSL-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//////////////////////////////////////////////////////////////////
//Includes
#include"Constants.fx"
#include"Sampler.fx"
#include"Textures.fx"
#include"Lighting.fx"


//////////////////////////////////////////////////////////////////
//Layout
struct VSInput
{
    uint IID                    : SV_InstanceID;
    float3 vPosition            : POSITION0;
    float3 vNormal              : NORMAL0;
    float3 vTangent             : TANGENT0;
    float2 vTextureCoord        : TEXCOORD0;
};

struct PSInput
{
    uint IID                    : INSTANCEID;
    float4 vPosition            : SV_Position;
    float3 vWorldPosition       : POSITION0;
    float3 vNormal              : NORMAL0;
    float3 vTangent             : TANGENT0;
    float3 vBinormal            : BINORMAL0;
    float2 vTextureCoord        : TEXCOORD0;
};

struct PSOutput
{
    float4 Color   : SV_Target0;
};

//VertexShader
PSInput VertexShaderProc(VSInput In)
{
    PSInput Out;
    
    Out.IID= In.IID;
    
    float4 vWorldPosition= mul(float4(In.vPosition, 1.0), Instance[In.IID].mWorld);
    Out.vPosition= mul(vWorldPosition, mViewProjection);
    
    Out.vWorldPosition= vWorldPosition.xyz;
    float3 vNormal= mul(In.vNormal, (float3x3)Instance[In.IID].mWorld);
    Out.vNormal= vNormal;
    
    Out.vTangent= mul(In.vTangent, (float3x3)Instance[In.IID].mWorld);
    Out.vBinormal= cross(Out.vTangent, Out.vNormal);
    
    Out.vTextureCoord= In.vTextureCoord;
    
    return(Out);
}

//PixelShader
PSOutput PixelShaderProc(PSInput In)
{
    PSOutput Out;
    
    //NormalMapping
    column_major float3x3 mTBN= {In.vTangent, In.vBinormal, In.vNormal};
    float3 vNormal= mul(TexNormalHeight.Sample(TextureSamplerWrap, In.vTextureCoord).rgb * 2.0 - 1.0, mTBN);
    
    //Illumination
    float3 SpecularLight= float3(0, 0, 0);
    float3 vViewDir= float3(mView._31, mView._32, mView._33);
    LightSource Light;
    uint LightIndex;

    //Light #0 (Directional)
    LightIndex= Instance[In.IID].aLightIndices[0].LID;
    if(LightIndex != 0xFFFFFFFF)
    {
        Light= aLights[LightIndex];
        SpecularLight+= DirectionalLightSpecular(Light, vNormal, MatSpecularColorPower.a, vViewDir);
    }

    //Color-Sources
    float4 ColorAlpha= MatColorAlpha;
    float4 SpecularColorPower= MatSpecularColorPower;
    float4 EmissiveAmbient= MatEmissiveAmbient;
    float4 MirrorColorSaturation= MatMirrorColorSaturation;
    
    ColorAlpha*= TexColorAlpha.Sample(TextureSamplerWrap, In.vTextureCoord);
    
    Out.Color= float4(0, 0, 0, 1);
    Out.Color.rgb+= AmbientLight.rgb * EmissiveAmbient.a * ColorAlpha.rgb;
    Out.Color.rgb+= SpecularLight * SpecularColorPower.rgb;
    
    return(Out);
}


Findet jemand den Fehler?

2

13.11.2010, 16:58

Was soll das werden? Ein Quiz-Spiel?
Sag lieber mal, was/wo dein Problem ist!
fka tm

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

3

13.11.2010, 17:07

Das Problem ist, dass das Endergebnis falsch ist. Wenn ich ein Objekt drehe, drehen sich die Lichtflecken (specular) mit dem Objekt mit, als würde sich auch die Lichtquelle drehen. Und ich weiß nicht warum. Das ist mein Problem.

EDIT: Kleines Beispiel.
Ein Quad mit Normalmapping auf X-Y Ebene um Z-Achse.
Kamera bei (0 0 -10) sieht entlang Z-Achse.
DirectionalLight in Richtung (1 0 1).

Durch die Normalmapp müssten sich die Lichtflecken links von Bumps und Schatten rechts von Bumps befinden. Aber sie rotieren mit den Quad mit! Eben als würde sich die Lichtquelle auch mitdrehen, das tut sie aber nicht.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »BlazeX« (13.11.2010, 17:47)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

13.11.2010, 18:37

Bist du dir sicher dass die Multiplikationsreihenfolge von Normale und Tangentspace Matrix passt? Das column_major beeinflusst ja nur wie die Matritzen intern repräsentiert werden, ich bin mir da nicht so sicher dass der Compiler da nicht autom. drauf Rücksicht nimmt sodass die Initialisierung erst wieder die Zeilen füllt und du bei mul() trotzdem anders rum multiplizieren musst. Versuch mal das column_major wegzunehmen und einfach mul(mTBN, normal) zu machen. Abgesehen davon: Hast du schon überprüft ob die Tangente und Bitangente überhaupt richtig sind? Wenn die nicht stimmen ist jede weitere Diskussion sowieso sinnlos...

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

5

13.11.2010, 20:52

Tangente und Bitangente stimmen.

Ohne column_major und mit vertauschten Parametern ergibt es nur Unsinn.

Ich glaube, der Fehler liegt, darin, dass die Normalen im PixelShader im TangentSpace liegen und nicht im WorldSpace.
Wenn das stimmt, habe ich jetzt 2 Möglichkeiten:
1.) Alle Lichtquellen in den TangentSpace transformieren, dazu noch die Blickrichtung.
2.) Die Normalen in den WorldSpace bringen.

Ersteres wäre mit viel Umstellung verbunden, letzteres hab ich keinen Plan, wie das geht.

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

6

13.11.2010, 21:19

transformiere das licht in den tangent space, dazu ist er schliesslich da. die matrix dafür hast du ja im vertex-shader.
ansonsten hast du beachtet, dass die normalen mit der inversen-transponierten weltmatrix transformiert werden sollte?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

13.11.2010, 21:24

Stimmt sry hab mich verwirren lassen. Es kommt eben drauf an was genau du tun willst. Natürlich liegen die Normalen die aus der Normal Map kommen im Tangent Space (zumindest wenn du eine Tangent Space Normal Map hast. Es gibt z.B. auch Object Space Normal Maps. Falls du nicht sicher weißt was du hast: Wenn die Normal Map sehr bunt ist dann ist es vermutlich eine Object Space Map, wenn sie eher Violett ist (die häufiger benutzte Variante) dann ist es eine Tagent Space Normal Map). Um die Normalen in den Worldspace zu bekommen musst du eine Matrix aus Worldspace (!) Tangente, Bitangente und Normale bauen und deine Normale damit multiplizieren. Um die Lichtquellen aus dem Worldspace in den Tangent Space zu bekommen brauchst du die inverse derselben Matrix. Dazu gehst du von der Vereinfachung aus dass Tangente, Bitangente und Normale eine orthonormale Basis bilden (paarweise normal aufeinander stehen und normalisiert sind). Eine Matrix aus orthonormalen Basisvektoren ist eine orthogonale Matrix für die gilt dass ihre Inverse gleich ihrer Transponierten ist. D.h. wenn du statt Vektor * Matrix einfach Matrix * Vektor rechnest transformierst du in dem Fall in die andere Richtung...

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (13.11.2010, 21:29)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

13.11.2010, 21:28

transformiere das licht in den tangent space, dazu ist er schliesslich da. die matrix dafür hast du ja im vertex-shader.
ansonsten hast du beachtet, dass die normalen mit der inversen-transponierten weltmatrix transformiert werden sollte?

Nun, in welche Richtung er transformieren muss hängt davon ab was genau er tun will. Wenn er z.B. nicht nur Beleuchtung sondern auch Environment Bump Mapping machen will muss er wohl vom Tangent Space in World Space transformieren...

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

9

13.11.2010, 21:43

Vor habe ich auf alle Fälle: Beleuchtung (auch Dot3-Bump-Mapping) mit mehreren Lichtquellen, Env-Bump-Mapping und POM.

Warum soll ich die Normalen mit der inv. transp. WorldMatrix multiplizieren? Ich benutze nur die innere 3x3-WorldMatrix für Normale, Tangente und Binormale. Da hebt das Transponieren doch das Invertieren auf. Oder nicht? Ohne Normalmap funktioniert die Beleuchtung ja, also würde ich es erstmal nicht auf die Normalen schieben.

dot: du sagtest "eine Matrix aus Worldspace (!) Tangente, Bitangente und Normale bauen"
Müsste meine TBN-Matrix im PixelShader nicht so eine Matrix sein? Normale, Binormale und Tangente habe ich im VertexShader mit der WorldMatrix multipliziert. Im PixelShader setze ich diese nur noch zun TBN-Matrix zusammen.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

10

13.11.2010, 22:00

Warum soll ich die Normalen mit der inv. transp. WorldMatrix multiplizieren?

Er wollte wohl generell darauf hinaus dass man Richtungsvektoren im allgemeinen Fall mir der inversen transponierten einer Transformationsmatrix multiplizieren muss. Wenn deine Matrix aber nur eine Rotation x Translation ist dann genügt einfach der obere 3x3 Teil.

dot: du sagtest "eine Matrix aus Worldspace (!) Tangente, Bitangente und Normale bauen"
Müsste meine TBN-Matrix im PixelShader nicht so eine Matrix sein? Normale, Binormale und Tangente habe ich im VertexShader mit der WorldMatrix multipliziert. Im PixelShader setze ich diese nur noch zun TBN-Matrix zusammen.

Ja, sollte so eine Matrix sein. Wie gesagt, verifiziere erstmal dass deine Tangente und Bitangente stimmen, wenn die falsch sind ist alles weitere sowieso sinnlos...

Vielleicht stimmt ja auch die World Matrix nicht, schonmal geprüft ob da alles richtig übergeben wird, von wegen column vs. row major etc.!?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (13.11.2010, 22:05)


Werbeanzeige