c++ - 如何保证齐次坐标中的向量经过变换后仍然是向量
问题描述
我MVP transformation
在模型的顶点上执行了一个。理论上,我必须将 MVP 变换的逆转置矩阵应用于normal。
这是推导过程:</p>
对于一个向量,例如(x0, y0, z0)
,它(x0, y0, z0, 0)
在齐次坐标中。变换后应该还是一个向量,如(x1, y1, z1, 0)
,这就要求4*4变换矩阵的最后一行除了最后一列的元素外全部为0,否则(x1, y1, z1, n)
变换后就变成了。
事实上,我的 MVP 变换矩阵在经过反转置变换后无法满足这一点。
代码:
Mat<4, 4> View(const Vec3& pos){
Mat<4, 4> pan{1, 0, 0, -pos.x,
0, 1, 0, -pos.y,
0, 0, 1, -pos.z,
0, 0, 0, 1};
Vec3 v = Cross(camera.lookAt, camera.upDirection).Normalize();
Mat<4, 4> rotate{v.x, v.y, v.z, 0,
camera.upDirection.x, camera.upDirection.y, camera.upDirection.z, 0,
-camera.lookAt.x, -camera.lookAt.y, -camera.lookAt.z, 0,
0, 0, 0, 1};
return rotate * pan;
}
Mat<4, 4> Projection(double near, double far, double fov, double aspectRatio){
double angle = fov * PI / 180;
double t = -near * tan(angle / 2);
double b = -t;
double r = t * aspectRatio;
double l = -r;
Mat<4, 4> zoom{2 / (r - l), 0, 0, 0,
0, 2 / (t - b), 0, 0,
0, 0, 2 / (near - far), 0,
0, 0, 0, 1};
Mat<4, 4> pan{1, 0, 0, -(l + r) / 2,
0, 1, 0, -(t + b) / 2,
0, 0, 1, -(near + far) / 2,
0, 0, 0, 1};
Mat<4, 4> extrusion{near, 0, 0, 0,
0, near, 0, 0,
0, 0, near + far, -near * far,
0, 0, 1, 0};
Mat<4, 4> ret = zoom * pan * extrusion;
return ret;
}
Mat<4, 4> modelMatrix = Mat<4, 4>::identity();
Mat<4, 4> viewMatrix = View(camera.position);
Mat<4, 4> projectionMatrix = Projection(-0.1, -50, camera.fov, camera.aspectRatio);
Mat<4, 4> mvp = projectionMatrix * viewMatrix * modelMatrix;
Mat<4, 4> mvpInverseTranspose = mvp.Inverse().Transpose();
MVP:
-2.29032 0 0.763441 -2.68032e-16
0 -2.41421 0 0
-0.317495 0 -0.952486 2.97455
0.316228 0 0.948683 -3.16228
mvpInverseTranspose:
-0.392957 0 0.130986 0
0 -0.414214 0 0
-4.99 0 -14.97 -4.99
-4.69377 0 -14.0813 -5.01
解决方案
我似乎明白了这个问题。光照应该是在世界空间中计算的,所以我只需要将 的逆转置矩阵the model transformation
应用于normal。
推荐阅读
- wagtail - 使用 api (wagtail) 创建新页面
- c# - C# WinForms - 代码在数组之前工作,但放在数组之后会失败
- python - 如何将 csv 转换为具有特定版本的 parquet 文件。(parquet-cpp 版本 1.5.1-SNAPSHOT)?
- terraform - Terraform cidrsubnet 函数
- c - 函数错误的参数太多,但函数显然需要两个参数
- c# - BindingSource 不向表中添加数据
- javascript - 清除 react-bootstrap 中的特定选择
- c# - 在等待挂起的操作取消时处置 SemaphoreSlim 是否安全?
- flutter - Flutter中UniqueKey的范围是什么?
- javascript - 输入提示输入后关闭分机