Yury Finchenko
Yury Finchenko

Reputation: 1065

GLSL normal vector transformation

In this glsl shader sample some vertex normal converted to the view space by transform: vec4(vertNormal,1.0)).xyz Why we need to do this kind of the transformation?

#version 430
layout (location=0) in vec3 vertPos;
layout (location=1) in vec3 vertNormal;

void main(void)
{ 
...


// convert vertex position to view space
vec4 P = mv_matrix * vec4(vertPos,1.0); // looks good

// convert normal to view space
vec3 N = normalize((norm_matrix * vec4(vertNormal,1.0)).xyz); // why to vec4 and back to vec3?
...
}

Upvotes: 1

Views: 7302

Answers (1)

Rabbid76
Rabbid76

Reputation: 210877

The model view matrix looks like this:

( X-axis.x, X-axis.y, X-axis.z, 0 )
( Y-axis.x, Y-axis.y, Y-axis.z, 0 )
( Z-axis.x, Z-axis.y, Z-axis.z, 0 )
( trans.x,  trans.y,  trans.z,  1 )

The upper let 3*3 is contains the orientation and the scale. The 4th row contains the translation.
While for the transformation of a point the full matrix has to take into account, for the transformation of a direction vector only the orientation is of interest.

In general the normal matrix is a mat3 and the inverse, transposed of the upper left 3*3 of the model view matrix. See

 mat3 norm_matrix;

 vec3 = normalize(norm_matrix * vertNormal);

The normal matrix can be calculated from the model view matrix:

mat4 mv_matrix;

mat3 norm_matrix = transpose(inverse(mat3(mv_matrix));
vec3 N = normalize(norm_matrix * vertNormal);

If the model view matrix is an Orthogonal matrix then the inverse, transpose can be skipped, because the inverse matrix is equal to the transposed matrix.
See In which cases is the inverse matrix equal to the transpose?

vec3 N = normalize(mat3(mv_matrix)* vertNormal);

If you want to do the calculations in view space, then you have to transform the vertex coordinate from model space to view space:

vec4 P = mv_matrix * vec4(vertPos,1.0);

and you have to transform the direction of the normal vector form model space to view space:

vec3 N = normalize(norm_matrix * vertNormal);

Upvotes: 4

Related Questions