法向量变换细节记录
最近在做法向量变换的时候,踩了两个坑,记录一下相关的知识点
法向量做变换,最后一位是补0
我们知道,顶点在做变换的时候最后一位是 1.0,法线最后一位是补0.0
vec3 normCurrent = (getMatrixWorld() * vec4(normCurrent, 0.0)).xyz; // 法线变换
vec3 pointCurrent = (getMatrixWorld() * vec4(pointCurrent, 1.0)).xyz; // 顶点变换
这主要是因为,将法线的最后一位设为0,可以消除位移对法线的影响;
首先,法向量只是一个方向向量,不能表达空间中的特定位置。同时,法向量没有齐次坐标(顶点位置中的w分量)。这意味着,位移不应该影响到法向量。因此,如果我们打算把法向量乘以一个模型矩阵,我们就要从矩阵中移除位移部分,只选用模型矩阵左上角3×3的矩阵(注意,我们也可以把法向量的w分量设置为0,再乘以4×4矩阵;这同样可以移除位移)。对于法向量,我们只希望对它实施缩放和旋转变换。
使用世界变换的逆转置矩阵对法线进行变换
当我拥有物体坐标系下的法线,我想将其变换到世界坐标系,只需要乘一下model矩阵就可以了吗,答案是否定的,我们可以看一下这张图,当模型发生了不等比缩放的时候:
此时对法向量应用相同的变换,得到的法向量不再垂直于表面。(注意:等比缩放不会破坏法线,因为法线的方向没被改变,仅仅改变了法线的长度,而这很容易通过标准化来修复),法向量就不会再垂直于对应的表面了,这样光照就会被破坏。
那应该怎么对法向量进行变换呢,请看下面的推导,引用知乎上的回答:
refer
- https://learnopengl-cn.github.io/02 Lighting/02 Basic Lighting/
- https://www.zhihu.com/question/27739027