Opengl 透视矩阵背后的数学
我想创建自己的mvp矩阵作为练习Opengl 透视矩阵背后的数学,opengl,matrix,perspectivecamera,Opengl,Matrix,Perspectivecamera,我想创建自己的mvp矩阵作为练习 auto lookAt(Vec)(const Vec eye, const Vec center, const Vec up) if(isVector!Vec && Vec.dimension is 3){ auto z = (eye - center).unit; auto x = cross(up.unit, z); auto y = cross(z, x); alias Mat = Matrix!(Vec.T
auto lookAt(Vec)(const Vec eye, const Vec center, const Vec up)
if(isVector!Vec && Vec.dimension is 3){
auto z = (eye - center).unit;
auto x = cross(up.unit, z);
auto y = cross(z, x);
alias Mat = Matrix!(Vec.Type, 4, 4);
alias Vec4 = Vector!(Vec.Type, 4);
return Mat(Vec4(x, 0),
Vec4(y, 0),
Vec4(z, 0),
Vec4(0, 0, 0, 1)) * translate(-eye);
}
视图转换非常简单,我将其设置为沿负Z轴查看
但是透视矩阵有一些问题
y' = 1 / (tan(fov/2) * z
x' = 1 / (ar * tan(fov/2) * z
其中x'
和y'
是新的扭曲值。所以我想出了这个矩阵
Mat4f projection(float fov, float ar, float near, float far){
import std.math: tan;
auto tanHalfAngle = tan(fov/2.0f);
return Mat4f(
Vec4f(1.0f / (ar * tanHalfAngle) , 0, 0, 0),
Vec4f(0, 1.0f / tanHalfAngle, 0, 0),
Vec4f(0, 0, 1, 0),
Vec4f(0, 0, -1, 0));
}
Mat4f projection(float fov, float ar, float near, float far){
import std.math: tan;
auto tanHalfAngle = tan(fov/2.0f);
return Mat4f(
Vec4f(1.0f / (ar * tanHalfAngle) , 0, 0, 0),
Vec4f(0, 1.0f / tanHalfAngle, 0, 0),
Vec4f(0, 0, -1, 0),
Vec4f(0, 0, 1, 0));
}
我目前只是将其设置为Z
值始终为-1
。但是我犯了一个小错误,因为现在我正在除以-Z
问题是上面的矩阵是有效的。我目前正在渲染一个旋转的立方体,除了深度值之外,一切看起来都是正确的
但我真的很想要这个矩阵
Mat4f projection(float fov, float ar, float near, float far){
import std.math: tan;
auto tanHalfAngle = tan(fov/2.0f);
return Mat4f(
Vec4f(1.0f / (ar * tanHalfAngle) , 0, 0, 0),
Vec4f(0, 1.0f / tanHalfAngle, 0, 0),
Vec4f(0, 0, 1, 0),
Vec4f(0, 0, -1, 0));
}
Mat4f projection(float fov, float ar, float near, float far){
import std.math: tan;
auto tanHalfAngle = tan(fov/2.0f);
return Mat4f(
Vec4f(1.0f / (ar * tanHalfAngle) , 0, 0, 0),
Vec4f(0, 1.0f / tanHalfAngle, 0, 0),
Vec4f(0, 0, -1, 0),
Vec4f(0, 0, 1, 0));
}
但是立方体不再出现在屏幕上,我不明白为什么
auto view = lookAt(Vec3f(0, 0, -5), Vec3f(0, 0, 0), Vec3f(0, 1, 0));
auto proj = projection(PI/2, 4.0f/3.0f, 0.1f, 100);
我设置测试值
auto v = proj * view * Vec4f(0.5,0.5,0.5,1);
这是我在第一个矩阵中得到的输出,其中我除以-Z
Vec(-0.375, 0.5, -5.5, 5.5)
Vec(-0.0681818, 0.0909091, -1) // divided by w
这是我通过第二个矩阵得到的输出,其中我除以Z
Vec(-0.375, 0.5, 5.5, -5.5)
Vec(0.0681818, -0.0909091, -1) //divided by w
唯一改变的是标志
但是为什么我可以看到第一个矩阵的立方体,而第二个矩阵却没有呢?OpenGL的默认剪裁规则是在剪裁空间中制定的,因为所有满足以下不平等性的点都位于视锥体内:
-w <= x, y, z <= w
-w