从0开始做一个软渲染器 —— 法线变换
从0开始做一个软渲染器 —— 法线变换
1. 为什么要进行法线变换
如果只对模型的位置进行变换,例如旋转和缩放(位移不会改变法线),而不考虑法线进行相应变换,那么模型的光照就一整个乱掉。
2. 怎么进行法线变换
如果模型只是旋转或者XYZ等比例的缩放,那么法线直接乘以ModelMatrix
不会有什么问题,但是如果不是等比例的缩放就会出现问题,参考文章图形学 | Shader |用一篇文章理解法线变换、切线空间、法线贴图 - 知乎 (zhihu.com)
假设光线是垂直向-Z方向,光照强度 =
如果缩放比例ModelMatrix
的效果如下:
脸明显变白了,显然法线出现错误。
如何进行正确的法线变换参考下面文章:
正确的normal transform matrix为
求逆操作是一个消耗很大的过程,但是由于Scale Matrix, Rotate Matrix 和 Traslate Matrix
的特殊性可以直接避免普通矩阵的求逆操作,参考下面两篇文章:
- Fast 4x4 Matrix Inverse with SSE SIMD, Explained - Eric's Blog (lxjk.github.io)
- Stop Using Normal Matrix - Eric's Blog (lxjk.github.io)
按照公式(不考虑T变换)
代码如下:
V2F BasicShader::VertexShader(const Vertex& v)
{
V2F v2f;
v2f.m_WorldPos = v.m_Position * m_ModelMatrix;
v2f.m_ScreenPos = v.m_Position * m_ModelMatrix * m_VPMatrix;
//法线变换, 求变换矩阵
float MagX_Square = m_ModelMatrix.m_Mat[0][0] * m_ModelMatrix.m_Mat[0][0] +
m_ModelMatrix.m_Mat[0][1] * m_ModelMatrix.m_Mat[0][1] +
m_ModelMatrix.m_Mat[0][2] * m_ModelMatrix.m_Mat[0][2];
float MagY_Square = m_ModelMatrix.m_Mat[1][0] * m_ModelMatrix.m_Mat[1][0] +
m_ModelMatrix.m_Mat[1][1] * m_ModelMatrix.m_Mat[1][1] +
m_ModelMatrix.m_Mat[1][2] * m_ModelMatrix.m_Mat[1][2];
float MagZ_Square = m_ModelMatrix.m_Mat[2][0] * m_ModelMatrix.m_Mat[2][0] +
m_ModelMatrix.m_Mat[2][1] * m_ModelMatrix.m_Mat[2][1] +
m_ModelMatrix.m_Mat[2][2] * m_ModelMatrix.m_Mat[2][2];
Matrix4 normalMatrix = m_ModelMatrix;
normalMatrix.m_Mat[3][0] = 0;
normalMatrix.m_Mat[3][1] = 0;
normalMatrix.m_Mat[3][2] = 0;
normalMatrix.m_Mat[0][0] /= MagX_Square;
normalMatrix.m_Mat[0][1] /= MagX_Square;
normalMatrix.m_Mat[0][2] /= MagX_Square;
normalMatrix.m_Mat[1][0] /= MagY_Square;
normalMatrix.m_Mat[1][1] /= MagY_Square;
normalMatrix.m_Mat[1][2] /= MagY_Square;
normalMatrix.m_Mat[2][0] /= MagZ_Square;
normalMatrix.m_Mat[2][1] /= MagZ_Square;
normalMatrix.m_Mat[2][2] /= MagZ_Square;
v2f.m_Normal = v.m_Normal * normalMatrix;
v2f.m_Texcoord = v.m_TexCoord;
v2f.m_Color = v.m_Color;
return v2f;
}
结果如下图所示,符合预期:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律