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

idontknow

unregistriert

1

06.03.2014, 01:26

Tangent Space, Würfel Bump-Mapping

moin!

Ich versuche aktuell Bump-Mapping bei einem Würfel zu implementieren. Der Ansatz ist der folgende: beim erzeugen des Würfels berechne ich den Tangent-Vektor, welchen ich den Vertexdaten mitgebe. Im Vertexshader habe ich dann Zugriff auf Tangent-Vektor und die Normale und kann damit die Bitangente berechnen. Mit den 3 Vektoren kann ich dann eine Matrix für einen Basiswechsel in/aus dem Tangentspace ermitteln.
Im Vertex-Shader berechne ich also das Inverse der Matrix um die Normale aus der Bump-Map in den World Space zu transformieren.

Kurze Beschreibung der Szene: Ein Würfel der Ausmaße 2x2x2 mit Ursprung als Zentrum. Die Lichtquelle ist positioniert genau bei (2, 2, 2) (Punktlicht).

Auf dem Bild sieht man (links) die Normale (Worldspace) transformiert in [-1, 1]. Rechts sieht man das Punktprodukt aus Normale und Richtung zum Licht. Die Perspektive ist in beiden Bildern gleich, der Vertex auf den man schaut ist (1,1,1).
https://dl.dropboxusercontent.com/u/8495…world_space.png

Der Fehler ist hier offensichtlich auf der rechten Seite des Würfels. Ich bin aber etwas überfragt wieso. Die Normalen schauen ganz in Ordnung aus! Alles ist korrekt normalisiert.

Am Ende des Posts, der Code.
Ein Hinweis noch: Ich berechne momentan den Tangentenspace für je eins der 2 Faces (pro Seite des Würfels) und verwende diese Tangente einfach für alle 4 Vertizes. Dass das ganze nicht 100%ig stimmen kann ist mir klar. Alternativ habe ich versucht pro Face die Tangente zu berechnen und bei den 2 Vertice die an beide Faces anliegen die Tangente zu mitteln. Das Ergebnis sah aber noch fehlerhafter aus als das jetzt.

Ich glaube aber irgendwie, dass der Fehler beim berechnen der Tangente liegt.. andererseits sehen die Normals ganz gut aus. Ich ibin etwas überfragt.. daher: Help!

Vertexsshader-Snippet:

HLSL-Quelltext

1
2
3
4
5
    // calculate matrix 
    vec3 biTangentVector = cross(tangentVector, normal);
    tangentSpace[0] = tangentVector;
    tangentSpace[1] = biTangentVector;
    tangentSpace[2] = normal;

Fragmentshader-Snippet:

HLSL-Quelltext

1
2
3
4
vec3 lightDir = normalize(light.Position - worldPos);
    vec3 bumpMapNormal = texture(normalMap, texCoord).xyz;
    vec3 normal = tangentSpace * (2) * bumpMapNormal.xyz - vec3(1);
    float dotProduct = dot(normal, lightDir);


Vertizes der fehlerhaften Seite:

C-/C++-Quelltext

1
2
3
4
5
    // front face
    glm::vec3(-1.0, -1.0, 1.0),
    glm::vec3(+1.0, -1.0, 1.0),
    glm::vec3(+1.0, +1.0, 1.0),
    glm::vec3(-1.0, +1.0, 1.0)

Indizes der fehlerhaften Seite:

C-/C++-Quelltext

1
20, 21, 22, 20, 22, 23


Berechnung des Tangentenvektors:

C-/C++-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
for (unsigned i = 0; i < 6; i++) // per face
        {
            glm::vec3 tangentVecOne;
            {
                unsigned triOne[3] = {
                    indices[i * 6 + 0],
                    indices[i * 6 + 1],
                    indices[i * 6 + 2]
                };


                glm::vec3 edge21 = positions[triOne[1]] - positions[triOne[0]];
                glm::vec2 edge21Tex = texCoords[triOne[1]] - texCoords[triOne[0]];

                glm::vec3 edge31 = positions[triOne[2]] - positions[triOne[0]];
                glm::vec2 edge31Tex = texCoords[triOne[2]] - texCoords[triOne[0]];


                if (edge21Tex.x == 0.0f)
                {
                    tangentVecOne = glm::normalize(edge31 / edge31Tex.x);
                }
                else
                {
                    tangentVecOne = glm::normalize(edge21 / edge21Tex.x);
                }

                glm::vec3 normalVec = normals[i * 4];
                //glm::vec3 biTangentVec = glm::cross(tangentVecOne, normalVec);
            }
            tsAxis[i * 4 + 1] = tangentVecOne;
            
            glm::vec3 tangentVecTwo;
            {
                unsigned triOne[3] = {
                    indices[i * 6 + 3],
                    indices[i * 6 + 4],
                    indices[i * 6 + 5]
                };


                glm::vec3 edge21 = positions[triOne[1]] - positions[triOne[0]];
                glm::vec2 edge21Tex = texCoords[triOne[1]] - texCoords[triOne[0]];

                glm::vec3 edge31 = positions[triOne[2]] - positions[triOne[0]];
                glm::vec2 edge31Tex = texCoords[triOne[2]] - texCoords[triOne[0]];


                if (edge21Tex.x == 0.0f)
                {
                    tangentVecTwo = glm::normalize(edge31 / edge31Tex.x);
                }
                else
                {
                    tangentVecTwo = glm::normalize(edge21 / edge21Tex.x);
                }

                glm::vec3 normalVec = normals[i * 4];
            }
            tsAxis[i * 4 + 3] = tangentVecTwo;
            
            glm::vec3 avgTangentVec = (tangentVecOne + tangentVecTwo) / 2.0f;
            tsAxis[i * 4 + 0] = tsAxis[i * 4 + 2] = avgTangentVec;

            tsAxis[i * 4] = tsAxis[i * 4 + 1] = tsAxis[i * 4 + 2] = tsAxis[i * 4 + 3] = tangentVecOne;
        }

FSA

Community-Fossil

  • Private Nachricht senden

2

06.03.2014, 19:23

Funktioniert denn alles, wenn du keine Normal-Map benutzt?

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

CodingCat

1x Contest-Sieger

Beiträge: 420

Beruf: Student (KIT)

  • Private Nachricht senden

3

06.03.2014, 19:48

HLSL-Quelltext

1
2
3
4
5
// Was ist denn das für ein Unfug? Punkt vor Strich! ;-)
vec3 normal = tangentSpace * (2) * bumpMapNormal.xyz - vec3(1);
// Davon abgesehen ist es gut möglich, dass Z in der
// Normalmap kein Biasing erfordert, da Normalen in
// Normalmaps in der Regel immer weg von der Oberfläche zeigen

Weiterhin ist es keine gute Idee, die ganze Matrix von Vertex in Fragment Shader zu verschieben, mehr als 4 interpolierte Vektoren ziehen die Performance in der Regel ordentlich in den Keller. Wenn du die eh nur aus Tangente und Normale berechnest, mach das lieber gleich im Fragment Shader.

Was rechnest du denn bei der Bestimmung der Tangente? Selbst ausgedacht? Wenn ja - hervorragend dass du es probierst, erklär mal was du da tust! - wenn nein - Quelle?
alphanew.net (last updated 2011-06-26) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »CodingCat« (06.03.2014, 19:58)


idontknow

unregistriert

4

07.03.2014, 01:29

Funktioniert denn alles, wenn du keine Normal-Map benutzt?

Naja was meinst du mit ohne Normal-Map? Der Würfel wird problemlos mit Textur gezeichnet für alles weitere ist ja die Normale notwendig..

HLSL-Quelltext

1
2
3
4
5
// Was ist denn das für ein Unfug? Punkt vor Strich! ;-)
vec3 normal = tangentSpace * (2) * bumpMapNormal.xyz - vec3(1);
// Davon abgesehen ist es gut möglich, dass Z in der
// Normalmap kein Biasing erfordert, da Normalen in
// Normalmaps in der Regel immer weg von der Oberfläche zeigen

Weiterhin ist es keine gute Idee, die ganze Matrix von Vertex in Fragment Shader zu verschieben, mehr als 4 interpolierte Vektoren ziehen die Performance in der Regel ordentlich in den Keller. Wenn du die eh nur aus Tangente und Normale berechnest, mach das lieber gleich im Fragment Shader.

Was rechnest du denn bei der Bestimmung der Tangente? Selbst ausgedacht? Wenn ja - hervorragend dass du es probierst, erklär mal was du da tust! - wenn nein - Quelle?


Oke eins nach dem anderen :p.
(1) hab die Matrix als flat deklariert, also sollte da nichts interpoliert werden, aber gut kanns im FS berechnen ist ja kein Ding.
(2) das Punkt vor Strich ist echt Müll, Danke
(3) Wegen dem Bias: also nur bumpMapNormal.xz transformieren in [-1, 1]?

Habs leider nicht selber ausgedacht, aber glaube es zumindest verstanden zu haben (einigermaßen, eigntlich klingt es nicht so wild deswegen ist es nahe liegend, dass ichs doch nicht verstanden habe). Als Quelle habe ich das hier benutzt: http://www.gamasutra.com/view/feature/12…ace.php?print=1
Ich hab im IRC schon mit xTr1m darüber gesprochen bzw er hat mir versucht weiterzuhelfen wss jetzt darin resultiert hat (im Grunde) eher diesr Quelle http://www.terathon.com/code/tangent.html zu vertrauen. Die Implementierung, wie es in letzterem erklärt wird, hat aber den selbn Fehler erzeugt, ABER ich hab eben noch nicht die Implementierung des Bitangentenvorzeichens (left-hand oder right-hand side Texturspace) fertig bekommen.

Ich bin generell etwas verzweifelt: Eigentlich stelle ich doch nur ein Orthonormalsystem meines Textur Raums auf und eben weil es ein Orthonormalsystem ist kann ich Problemlos eine Basiswechselmatrix in/aus dem Objekt Raum erzeugen. Daher mü+sste das eigentlich total einfach sein, gerade hier beim Würfel! Eine beliebige Kante eines Faces als Tangente wählen, die Normale ist gegeben und Bitangente kann ich durchs Kreuzprodukt berechnen. Damit habe ich 3 Vektoren die normalisiert ein orthonormalsystem erzeugen und das ist ja genau das was ich brauche.

Wenn das aber nicht funktioniert (was es ja nicht tut) bin ich einfach komplett überfragt :'(

Shit, der Fehler mit der Punkt vor Strichrechnung war das Problem... Danke Cat!!

Ergebnisbild (habs mir irgendwie spektakulärer vorgestellt sieht ja doch bescheiden aus :S)

(Link)

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »idontknow« (07.03.2014, 01:37)


5

08.03.2014, 18:54

// Edit: Fehlerhafter Post.

Werbeanzeige