GLSL normal mapping (Dot3 bump mapping)

Die TBN Matrix

Ich hoffe die folgende Zusammenfassung ist für die Leute hilfreich, die etwas verwirrt sind, in welche Richtung ein Vektor mit Hilfe der TBN Matrix nun transformiert wird.

Im Netz geistern nämlich unzählige Artikel rum, in denen die TBN Matrix mal in den object space transformiert, mal in den world space und mal in den tangent space.

Die folgenden Punkte nacheinander abgearbeitet, führen zu einem funktionierenden Shader mit schickem normal mapping und sollten die Zusammenhänge verdeutlichen:

1. TBN Matrix für jeden Vertex erstellen. Die TBN Matrix besteht aus drei Vektoren (tangent, binormal, normal). Sie transformiert einen Punkt V vom tangent space in den object space und ist wie folgt aufgebaut:

(Tx, Bx, Nx)
(Ty, By, Ny) * V
(Tz, Bz, Nz)

Von den drei Vektoren tangent, binormal und normal muss aber nur tangent und normal als Attribut an den Shader übergeben werden. Die face normal ist identisch mit der TBN normal und kann daher auch für die TBN Matrix verwendet werden. Die binormal wird per Kreuzprodukt im Shader errechnet.

2. Tangent und face normal können durch Addition mit den tangent und normal Vektoren der benachbarten faces und abschließender Normalisierung „gesmoothed“ werden. Z.B. mit Hilfe von smoothing groups.

3. Tanget und face normal mit der Matrix multiplizieren, die vom object in den world space transformiert (also mit der Matrix, die für die Objektrotation zuständig ist). Das ergibt eine TBN Matrix (bzw dessen tangent und normal), welche einen Punkt V vom tangent space in den world space transformiert.

4. Im Shader wird diese face normal sowie tangent noch mit der NormalMatrix (ähnlich der ModelViewMatrix) multipliziert. Die binormal wird jetzt durch das Kreuzprodukt berechnet. Nun hat man eine TBN Matrix, welche vom tangent space in den camera/eye space transformiert.

5. Die Inverse davon transformiert einen Punkt P vom camera/eye space in den tangent space. Das ist also die entgültige TBN Matrix, die alle für die Lichtberechnung nötigen Vektoren in den tangent space transformiert. Sie entspricht der transponierten TBN Matrix, da deren Basisvektoren orthogonal sind:

(Tx, Ty, Tz)
(Bx, By, Bz) * P
(Nx, Ny, Nz)

Diese Multiplikation mit der inversen TBN Matrix (bzw. der transponierten TBN Matrix) kann man dann im Shader auch so schreiben:

(T dot P)
(B dot P)
(N dot P)

Darum heißt das ganze IMHO auch Dot3 bump mapping. Nachdem alle benötigten Vektoren mit diesen drei dot products in den tangent space transformiert wurden, kann man endlich mit den normals aus der normal map rechnen, welche ja bereits im tangent space liegen und diesen ganzen Zirkus erst nötig gemacht haben.

Happy coding!

OpenGL 1.X functions and gl3.h

How-to bind OpenGL 1.0 and 1.1 functions in the new OpenGL 3.2 context (core profile) on Windows when using the gl3.h header

For OpenGL 3 and above it is a good practice to use the new gl3.h header which does not include any deprecated functions from older OpenGL versions.

If you replace your gl.h (and maybe also the glext.h) header with the new gl3.h file the first thing you may notice is that the fundamental functions like glGetError() are not ready to use.

You could define GL3_PROTOTYPES but maybe that is not what you want to do because Windows’s opengl32.dll does not provide the necessary implementations for all the functions defined in gl3.h’s #ifdef GL3_PROTOTYPES […] #endif blocks. In fact Windows’s native OpenGL implementation only contains implementations for OpenGL 1.0 and 1.1 since Microsoft left the Khronos Group.

So instead of defining GL3_PROTOTYPES one has to use the function pointers provided below each #ifdef GL3_PROTOTYPES […] #endif block.

But the 1.0 and 1.1 functions declared in gl3.h cannot be bound via wglGetProcAddress()! Instead one has to load the opengl32.dll and then bind the functions via GetProcAddress():

HMODULE handle = NULL;

PROC getGlAddr(string procedure)
{
    PROC address= wglGetProcAddress(procedure.c_str());

    if (!address)
    {
        address= GetProcAddress(handle, procedure.c_str());
    }

    return address;
}

handle= LoadLibraryA("opengl32.dll");

glGetError= (PFNGLGETERRORPROC) getGlAddr("glGetError");

FreeLibrary(handle);

Die besten Horrorfilme

Auf der Suche nach guten Horrorfilmen stolpert man im Netz über Foren und Blogs, in denen oft kitschige Filme (z.B. Scream) oder Zombistreifen genannt werden. Noch ermüdender, die dort genannten Filme gehören oft einem ganz anderen Genre an (z.B. Thriller oder Splatter/Gorefilme wie Hostel und Saw).

Darum sollen an dieser Stelle mal die besten „echten“ Horrorfilme genannt werden:

  1. Der Exorzist – Director’s Cut (Teil 1!)
  2. Der Babadook
  3. Paranormal Activity 1 und 2
  4. The Grudge 1
  5. The Ring 1 und 2
  6. The Descent 1
  7. It Follows
  8. The Visit
  9. Drag Me To Hell
  10. The Shining
  11. The Conjuring
  12. Insidious 1 und 2
  13. The Pact
  14. Mama 2013

Der beste Horrorfilm ist also IMHO Der Exorzist – Director’s Cut. Er kommt wie eine Dokumentation rüber, in der die Grenzen der Medizin deutlich gemacht werden. Darüber hinaus wird der Teufel in Person, wie in keinem anderen Film, vor allem durch vulgäre Sprache inszeniert.