Voor een engine die ik aan het maken ben (deferred renderer puur om met technieken te stoeien). Genereer ik een terrain (met vertices en indices).
In de index buffer sla ik op welke index in de array vertices de vertices hebben die samen een driehoek vormen.
De eerste driehoek is bestaat dus uit vertices[indices[0]], vertices[indices[1]], vertices[indices[2]].
Anyway, voor de shader (ivm normal mapping) zou ik graag de normal, binormal en tangent uit rekenen zodat ik die per vertex (in mijn vertex data) kan opslaan.
Dit heb ik op de volgende manier gepoogd te doen:
Normals genereer ik op de volgende manier, deze formule heb ik op internet gevonden en is redelijk recht-toe-recht-aan.
Een tangent (raaklijn) genereren leek heel moeilijk te vinden, maar uiteindelijk heb ik dit geschreven:
De binormal is dan weer heel makkelijk te vinden
Van alle stukken code ben ik redelijk zeker dat ze goed zijn, behalve van het genereren van de tangents. Anyway om het te testen heb met dezelfde shader als dat ik een model render het terrain gerendered. Met dit als resultaat:

De normal/tangent/binormal data wordt in de shader gecombineerd, dit gaat goed bij het model (de normal, binormal en tangent data wordt daarbij gegenereerd door het framework), je ziet verschillende hoeken duidelijk onder verschillende kleuren. Maar bij het terrein zie je veel minder duidelijk verschillende kleuren, alles is een variant van groen. (Wat betekend dat het Y-coordinaaat somehow altijd de dominante factor is). Hierdoor vermoed ik dat er iets helemaal fout gaat. Vermoedelijk is dat tangent berekening.
Heeft iemand enig idee/tips/inzicht wat er aan de hand is?
(Overigens gebruik ik XNA die Right-Hand-Coordinate space, dus daar is de code ook op gebaseerd)
In de index buffer sla ik op welke index in de array vertices de vertices hebben die samen een driehoek vormen.
De eerste driehoek is bestaat dus uit vertices[indices[0]], vertices[indices[1]], vertices[indices[2]].
Anyway, voor de shader (ivm normal mapping) zou ik graag de normal, binormal en tangent uit rekenen zodat ik die per vertex (in mijn vertex data) kan opslaan.
Dit heb ik op de volgende manier gepoogd te doen:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| // For each triangle for (int i = 0; i < indices.Length; i += 3) { // Find the vertex of each corner of the triangle VertexPositionNormalTextureTangentBinormal v1 = vertices[indices[i]]; VertexPositionNormalTextureTangentBinormal v2 = vertices[indices[i + 1]]; VertexPositionNormalTextureTangentBinormal v3 = vertices[indices[i + 2]]; Vector3 normal = GenerateNormal(v1.Position, v2.Position, v3.Position); Vector3 tangent = GenerateTangent(v1.Position, v2.Position, v3.Position, v1.Texture, v2.Texture, v3.Texture); Vector3 binormal = GenerateBiNormal(normal, tangent); vertices[indices[i]].Normal += normal; vertices[indices[i]].Tangent += tangent; vertices[indices[i]].BiNormal += binormal; } |
Normals genereer ik op de volgende manier, deze formule heb ik op internet gevonden en is redelijk recht-toe-recht-aan.
C#:
1
2
3
4
5
6
7
| private static Vector3 GenerateNormal(Vector3 v1, Vector3 v2, Vector3 v3) { // Cross the vectors between the corners to get the normal Vector3 normal = Vector3.Cross(v1 - v2, v1 - v3); normal.Normalize(); return normal; } |
Een tangent (raaklijn) genereren leek heel moeilijk te vinden, maar uiteindelijk heb ik dit geschreven:
C#:
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
| private Vector3 GenerateTangent(Vector3 v1, Vector3 v2, Vector3 v3, Vector2 w1, Vector2 w2, Vector2 w3) { float x1 = v2.X - v1.X; float x2 = v3.X - v1.X; float y1 = v2.Y - v1.Y; float y2 = v3.Y - v1.Y; float z1 = v2.Z - v1.Z; float z2 = v3.Z - v1.Z; float s1 = w2.X - w1.X; float s2 = w3.X - w1.X; float t1 = w2.Y - w1.Y; float t2 = w3.Y - w1.Y; float r = 1.0f / (s1 * t2 - s2 * t1); Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); // Gram-Schmidt orthogonalize Plane plane = new Plane(v1, v2, v3); //create a plan from the three vertices, use the plane's normal Vector3 tangent = sdir - plane.Normal * Vector3.Dot(plane.Normal, sdir); tangent.Normalize(); return tangent; } |
De binormal is dan weer heel makkelijk te vinden
C#:
1
2
3
4
| private Vector3 GenerateBiNormal(Vector3 normal, Vector3 tangent) { return Vector3.Cross(normal, tangent); } |
Van alle stukken code ben ik redelijk zeker dat ze goed zijn, behalve van het genereren van de tangents. Anyway om het te testen heb met dezelfde shader als dat ik een model render het terrain gerendered. Met dit als resultaat:

De normal/tangent/binormal data wordt in de shader gecombineerd, dit gaat goed bij het model (de normal, binormal en tangent data wordt daarbij gegenereerd door het framework), je ziet verschillende hoeken duidelijk onder verschillende kleuren. Maar bij het terrein zie je veel minder duidelijk verschillende kleuren, alles is een variant van groen. (Wat betekend dat het Y-coordinaaat somehow altijd de dominante factor is). Hierdoor vermoed ik dat er iets helemaal fout gaat. Vermoedelijk is dat tangent berekening.
Heeft iemand enig idee/tips/inzicht wat er aan de hand is?
(Overigens gebruik ik XNA die Right-Hand-Coordinate space, dus daar is de code ook op gebaseerd)
[ Voor 0% gewijzigd door RobIII op 31-01-2011 18:59 . Reden: Code tags gefixed :P Prutz0r :P ]