GLSL法线向量变换

Posted

技术标签:

【中文标题】GLSL法线向量变换【英文标题】:GLSL normal vector transformation 【发布时间】:2018-11-07 15:21:59 【问题描述】:

在这个 glsl 着色器示例中,一些顶点法线通过变换转换为视图空间:vec4(vertNormal,1.0)).xyz 为什么我们需要进行这种转换?

#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?
...

【问题讨论】:

反正这是错误的。对于Orthogonal matrix 和N = normalize(transpose(inverse(mat3(norm_matrix))) * vertNormal);,它必须是N = normalize(mat3(norm_matrix) * vertNormal); 【参考方案1】:

模型视图矩阵如下所示:

( 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 )

上面的 let 3*3 包含方向和比例。第 4 行包含翻译。 虽然对于点的变换必须考虑全矩阵,但对于方向向量的变换,只有方向是感兴趣的。

一般来说法线矩阵是模型视图矩阵左上角3*3的mat3inversetransposed。见

Why is the transposed inverse of the model view matrix used to transform the normal vectors? Why transforming normals with the transpose of the inverse of the modelview matrix?

 mat3 norm_matrix;

 vec3 = normalize(norm_matrix * vertNormal);

法线矩阵可以从模型视图矩阵中计算出来:

mat4 mv_matrix;

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

如果模型视图矩阵是Orthogonal matrix,则可以跳过inversetranspose,因为逆矩阵等于转置矩阵。 见In which cases is the inverse matrix equal to the transpose?

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

如果要在视图空间中进行计算,则必须将顶点坐标从模型空间转换到视图空间:

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

你必须将法线向量形式模型空间的方向转换到视图空间:

vec3 N = normalize(norm_matrix * vertNormal);

【讨论】:

以上是关于GLSL法线向量变换的主要内容,如果未能解决你的问题,请参考以下文章

法线变换需要右乘矩阵,顶点变换需要左乘矩阵

法线变换需要右乘矩阵,顶点变换需要左乘矩阵

[Unity Shader] 坐标变换与法线变换及Unity5新增加的内置函数

GLSL 大气散射不随变换缩放

着色器中的 OpenGL 法线变换

各语言系统或编程接口中向量与矩阵存储的差异