OpenGL Tutorial (Version 3.3) – World Space Normal Mapping (Download)

Im nachfolgenden OpenGL-Programmbeispiel lernen sie mit dem sogenannten World Space Normal Mapping eine zweite Technik für die pixelgenaue Beleuchtung im Fragment Shader kennen. Im Gegensatz zum sphärischen Normal Mapping werden die Textur-Normalen vor der Durchführung der eigentlichen Beleuchtungsberechnungen zunächst aus dem Texture Space in den World Space transformiert. Die hierfür benötigten Transformationsmatrizen werden in zwei Schritten generiert. Im ersten Schritt wird für jeden Vertex eine Matrix für die Transformation der Textur-Normalen aus dem Texture Space in den Model Space beim Laden des Asteroiden-Meshes berechnet und in einem erweiterten Vertexformat gespeichert:

struct CTexturedVertexWithNormal_NM
{
-->
    // Über
tw könnte man bsp. den Index der zu verwendenden Textur
    // festlegen:
    float tu, tv, tw;

    // die nachfolgenden 9 Variablen sind die Elemente der
    // Transformationsmatrix (Texture Space -> Model Space):
    float Perpendicular1X, Perpendicular1Y, Perpendicular1Z;
    float Perpendicular2X, Perpendicular2Y, Perpendicular2Z;
    float NormalX, NormalY, NormalZ;

    float PosX, PosY, PosZ; 
};

Um nun die Textur-Normalen in den World Space transformieren zu können, muss die Transformationsmatrix im Vertex Shader (NormalMapping.vert) zunächst mit der Rotationsmatrix des 3D-Models multipliziert werden:

-->// Rotation des Modells berücksichtigen:
gs_TexCoord[1].xyz = matRotation * gs_Normal;

-->// Perpendicular2:
gs_TexCoord[2].xyz = matRotation * gs_MultiTexCoord2.xyz;

-->// Perpendicular1:
gs_TexCoord[3].xyz = matRotation * gs_MultiTexCoord1.xyz;

Im Fragment Shader (NormalMapping.frag) wird schließlich die Matrix zusammengesetzt und für die Transformation der Textur-Normalen eingesetzt:

mat3 matTexturespaceToWorldspace;

-->// Perpendicular2:
matTexturespaceToWorldspace[0] = gs_TexCoord[2].xyz;

-->// Perpendicular1:
matTexturespaceToWorldspace[1] = gs_TexCoord[3].xyz;

-->// Normal:
matTexturespaceToWorldspace[2] = gs_TexCoord[1].xyz;

vec3 NormalPerTexel = matTexturespaceToWorldspace*
     (2.0*texture(AsteroidNormalTexture, gs_TexCoord[0].st).rgb - 1.0);


Hinweis:
Für die Ausführung dieses Programmbeispiels muss der Treiber Ihrer Grafikkarte die OpenGL Version 3.3 unterstützen.

Visual C++ 2010: DemoWithOpenGL2010_Tut11