【发布时间】:2021-11-13 13:20:29
【问题描述】:
我一直在使用 glm 来帮助构建用于自学的软件光栅化器。在我的相机类中,我使用 glm::lookat() 创建视图矩阵,并使用 glm::perspective() 创建透视矩阵。
我似乎得到了我对左、右顶部和底部剪裁平面的期望。但是,我似乎对我的近/远飞机做错了什么,或者我的理解有误。我的“google-fu”已经到了让我失望的地步。
在我正确地从我的 glm::perspective 矩阵中提取剪切平面的假设下进行操作,并使用一般平面方程:
aX+bY+cZ+d = 0
我的 zNear 和 zFar 平面出现了奇怪的 d 或 "offset" 值。 据我了解,d 值是我将沿法线向量移动/平移平面的点 P0 的值。
它们分别是 0.200200200 和 -0.200200200。但是,对于垂直于我的 z 基向量的平面,我的法线正确地定向为沿 z 轴的 +1.0f 和 -1.f。
因此,当针对这些平面测试 (0, 0, -5) 世界空间之类的点时,它会被我的视图矩阵转换为:
(0, 0, 5.81181192)
因此在剪辑链中针对这些平面进行测试,所述示例顶点将被剔除。
这是建立相关矩阵的相机类的开始:
static constexpr glm::vec3 UPvec(0.f, 1.f, 0.f);
static constexpr auto zFar = 100.f;
static constexpr auto zNear = 0.1f;
Camera::Camera(glm::vec3 eye, glm::vec3 center, float fovY, float w, float h) :
viewMatrix{ glm::lookAt(eye, center, UPvec) },
perspectiveMatrix{ glm::perspective(glm::radians<float>(fovY), w/h, zNear, zFar) },
frustumLeftPlane {setPlane(0, 1)},
frustumRighPlane {setPlane(0, 0)},
frustumBottomPlane {setPlane(1, 1)},
frustumTopPlane {setPlane(1, 0)},
frstumNearPlane {setPlane(2, 0)},
frustumFarPlane {setPlane(2, 1)},
平截头体对象基于以下结构:
struct Plane
{
glm::vec4 normal;
float offset;
};
我从透视矩阵中提取了 6 个剪切平面,如下所示:
Plane Camera::setPlane(const int& row, const bool& sign)
{
float temp[4]{};
Plane plane{};
if (sign == 0)
{
for (int i = 0; i < 4; ++i)
{
temp[i] = perspectiveMatrix[i][3] + perspectiveMatrix[i][row];
}
}
else
{
for (int i = 0; i < 4; ++i)
{
temp[i] = perspectiveMatrix[i][3] - perspectiveMatrix[i][row];
}
}
plane.normal.x = temp[0];
plane.normal.y = temp[1];
plane.normal.z = temp[2];
plane.normal.w = 0.f;
plane.offset = temp[3];
plane.normal = glm::normalize(plane.normal);
return plane;
}
任何帮助将不胜感激,因为我现在不知所措。
非常感谢。
【问题讨论】:
-
您到底想实现什么?裁剪(由 OpenGL 完成)发生在投影步骤之后,并且不需要您从投影矩阵中获取裁剪平面。这是不相关的:使用布尔然后通过/测试数值是一种不好的做法。如果你有一个布尔值,请使用 true、false。
-
我没有直接使用 OpenGL。我正在创建一个软件渲染器,所以我必须自己实现所有的剪辑逻辑。我只是很困惑,为什么我的 zNear 和 zFar 平面如此靠近。
标签: matrix opengl graphics glm-math