Eine mögliche Implementierung von Normal Maps in GLSL mit Lighting-Berechnung im Tangent Space könnte so aussehen:
Vertex Shader
// Normale
in vec3 in_norm;
// Tangente wird vor dem Vertex-Shader berechnet,
// weil hierfür alle drei Vertices bekannt sein müssen.
in vec3 in_tan; // Tangente
// Im Tangent Space
out vec3 direction_ts;
void main() {
vec3 bi_tan = cross(in_norm, in_tan); // Bi-Tangente
// TBN vom Model-Space in Worldspace rechnen
vec3 T = normalize(vec3(model_normal * vec4(in_tan, 0)));
vec3 B = normalize(vec3(model_normal * vec4(bi_tan, 0)));
vec3 N = normalize(vec3(model_normal * vec4(in_norm, 0)));
// Tangent Space aufsetzen
mat3 TS = transpose(mat3(T, B, N));
// Richtungen in den Tangent Space rechnen
direction_ts = normalize(TS * direction_ws);
/* ... */
}Fragment Shader
Normal Maps sind Texturen, die wie gehabt in den Shader geladen und ausgelesen werden können.
in vec2 tc;
uniform int has_normalmap;
uniform sampler2D normalmap;
void main() {
/* ... */
// Fallback für die Normale
vec3 N = vec3(0,0,1);
if (has_normalmap == 1) {
// Normalenrichtung aus der Textur holen
vec4 n = texture(normalmap, tc);
// Normale aus Richtung bauen.
// Wertebereiche müssen gemapped werden:
// rgb: [0, 1] --> xyz: [-1, 1]
// Umrechung mit x --> 2x - 1
N = normalize(vec3(
n.r * 2 - 1,
n.g * 2 - 1,
n.b * 2 - 1
));
}
// N kann jetzt für z.B. Phong-Lighting verwendet
// werden, vorausgesetzt alle anderen Richtungen
// sind auch im Tangent Space.
/* ... */
}Siehe auch
