PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Vereinfachtes Normal Mapping


Schrittmacher
2006-11-27, 15:21:52
Hallo,

Ich suche nach einem vereinfachten Normal Mapping Verfahren, wo die Ebene der Normalentextur identisch mit der Dreiecksebene ist.
Es soll daher nicht zwischen den Dreiecken die Tangentialebenen interpoliert, sondern lediglich eine flache Ebene mit der Bump-Map versehen werden.

Mir stellt sich daher die Frage, wie ich das übliche Verfahren vereinfachen kann.
Allerdings fehlt mir die Geduld mir das mathematisch komplett alleine auszutüfteln.

Es währe daher toll wenn mir jemand zumindest Ansätze zukommen lassen könnte.

Vielen Dank für eure Hilfe!

Chris Lux
2006-11-27, 15:33:37
Hallo,

Ich suche nach einem vereinfachten Normal Mapping Verfahren, wo die Ebene der Normalentextur identisch mit der Dreiecksebene ist.
Es soll daher nicht zwischen den Dreiecken die Tangentialebenen interpoliert, sondern lediglich eine flache Ebene mit der Bump-Map versehen werden.

in dem falle stellt die normale, die du aus der textur liest direkt die normale im object space dar. diese musst du nur noch mit der aktuellen modelview matrix (speziell die transponierte inverse davon) transformieren und kannst dein beleuchtungsmodell berechnen. hier ein kurzer shader code, der genau dies tut:
#version 120
varying vec3 view_dir;

uniform sampler2D _diff_gloss;
uniform sampler2D _normal;

void main()
{
vec4 diff_gloss = texture2D(_diff_gloss, gl_TexCoord[0].xy);
vec3 normal = texture2D(_normal, gl_TexCoord[0].xy).xyz * 2.0 - vec3(1.0);

normal = normalize(gl_NormalMatrix * normal);

vec3 l = normalize(gl_LightSource[0].position.xyz); // parallel light assumed
vec3 v = normalize(view_dir);
vec3 h = normalize(l + v);

vec3 res = diff_gloss.xyz * gl_LightSource[0].diffuse.xyz * max(0.0, dot(normal, l))
+ diff_gloss.a * gl_LightSource[0].specular.xyz * pow(max(0.0, dot(normal, h)), gl_FrontMaterial.shininess);

gl_FragColor = vec4(res, 1.0);

}

hier habe ich als beispiel die normale diffuse texture und die gloss map in einer rgba textur gespeichert. die normalen werden als 8bit rgb werte abgelegt und müssen deshalb noch entpackt werden (*2-1). danach wird die normale wie gesagt einfach transformiert und benutzt. im vertexshader passiert nicht viel, nur das normale transformieren und das berechnen des view vektors (welcher als varying zu den fragmenten interpoliert wird).

HTH

Gast
2006-11-27, 16:42:45
... und das berechnen des view vektors (welcher als varying zu den fragmenten interpoliert wird).Also einfach: OUT.viewDir = normalize(eyePos - position.xyz) ?

Chris Lux
2006-11-27, 16:53:54
Also einfach: OUT.viewDir = normalize(eyePos - position.xyz) ?
genau... oder einfach so unter der annahme des standard kamera modells, dass der eye punkt immer in (0, 0, 0)^T liegt:

#version 120
varying vec3 view_dir;

void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
view_dir = -normalize(gl_ModelViewMatrix * gl_Vertex).xyz;

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

Gast
2006-11-27, 17:33:27
Meine Erinnerung an Algebra ist extrem verfallen...

Wenn die Vertexnormalen variieren (also wenn verschiedene plane Ebenen in einer Vertexliste vorhanden sind), muss ich dann einfach die Texturnormale mit der Vertexnormale multiplizieren?

Gast
2006-11-27, 18:19:02
Äh ich meine natürlich addiert.

Also: normal = normalize(texNorm + VertNorm)

Zumindest mit Fingergymnastik und viel Hoffnung klappt das. LOL

Kann das mit Algebra-Wissen sagen ob dies wirklich korrekt ist?

Chris Lux
2006-11-27, 19:24:02
Äh ich meine natürlich addiert.

Also: normal = normalize(texNorm + VertNorm)

Zumindest mit Fingergymnastik und viel Hoffnung klappt das. LOL

Kann das mit Algebra-Wissen sagen ob dies wirklich korrekt ist?
was du damit berechnest ist der halbvektor zwischen surface normale und der normale aus der normal map. die normal map ist aber dafür da die surface normale am entsprechenden fragment zu liefern.

Gast
2006-11-27, 20:22:18
Na gut, nur wie kann ich dann die korrekte Normale aus Vertexnormale und Texturnormale berechnen? Oder kann man den Augen-/Lichtvektor entsprechend der Vertexnormale anpassen...

Denn ich will ja wie bereits gesagt nicht nur eine Ebene verarbeiten, sondern mehrere.

Nochmal Danke.

Neomi
2006-11-27, 21:16:04
Denn ich will ja wie bereits gesagt nicht nur eine Ebene verarbeiten, sondern mehrere.

Es gibt zwei Möglichkeiten: Tangentspace und Objectspace.

Wenn du die Normale in der Textur im Objectspace hinterlegst, mußt du sie nur noch mit der Worldmatrix transformieren (nur Rotation) und hast die Normale im Worldspace. Einen Teil der Normalmap kannst du nur dann auf mehreren Flächen verwenden, wenn alle Flächen die gleiche Ausrichtung haben, ansonsten bekommst du nicht das "gewünschte" Ergebnis.

Wenn du Teile der Map auf unterschiedlichen Dreiecken mit unterschiedlicher Ausrichtung benutzen willst, dann brauchst du den Tangentspace. Ohne geht es nicht. Wenn du bis D3D10 wartest, kannst du ihn eingeschränkt im Geometryshader generieren, aber du kommst nicht dran vorbei.

Schrittmacher
2006-11-27, 22:05:56
Was ich mit der Tangentialebene nicht verstehe: warum ist die Normale dieser Ebene (Tangente x Binomale) nicht gleich der Vertexnormalen?
Zumindest habe ich in den Dokumenten bisher gelesen dass dies so ist.
Warum gibt es da einen Unterschied?