关于使用glm::透视的zFar和zNear平面偏移的混淆



我一直在使用glm来帮助构建一个用于自我教育的软件光栅化器。在我的相机类中,我使用glm::look()来创建我的视图矩阵和glm::perspective()来创建我的透视矩阵。

我似乎得到了我所期望的左,右顶部和底部裁剪平面。然而,我似乎要么为我的近/远飞机做错了什么,要么我的理解有错误。我已经到了一个地步,我的"google-fu">让我失望了。

假设我正确地从glm::透视矩阵中提取剪辑平面,并使用一般平面方程:

aX+bY+cZ+d = 0

I am getting stranged"offset">值为我的zNear和zFar平面。我的理解是dvalue是我将平面上的点P0沿法向量移动/平移的值

分别为0.200200200和-0.200200200。然而,我的法线是正确的方向在+1.0f和-1。在垂直于z基向量的平面上沿z轴的F

所以当测试一个点,如(0,0,-5)世界空间对这些平面,它被我的视图矩阵转换为:

(0,0,5.81181192)

所以在clip chain中对这些平面进行测试,示例顶点将被剔除。

下面是一个camera类建立相关矩阵的开始:

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)},

frustum对象基于以下结构体:

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;
}

任何帮助将不胜感激,因为我现在无所适从。

许多谢谢。

平面方程的d参数描述平面沿法线距离原点的偏移量. 这也考虑了标准的长度。

如果不调整d参数,就不能仅仅规范化法线,因为规范化会改变法线的长度。如果你想标准化一个平面方程那么你还必须对d坐标应用除法步骤:

float normalLength = sqrt(temp[0] * temp[0] + temp[1] * temp[1] + temp[2] * temp[2]);
plane.normal.x = temp[0] / normalLength;
plane.normal.y = temp[1] / normalLength;
plane.normal.z = temp[2] / normalLength;
plane.normal.w = 0.f;
plane.offset = temp[3] / normalLength;

附注1:通常,人们会将平面方程的偏移量存储在vec4的w坐标中,而不是单独的变量中。原因是您对它执行的典型操作是像dist = n * x - d这样的点到平面距离检查(对于给定点x,法线n,偏移量d, *是点积),然后可以写成dist = [n, d] * [x, -1]

边注2:大多数软件和硬件光栅化器在投影步骤之后执行剪辑,因为它更便宜,更容易实现。

相关内容

  • 没有找到相关文章

最新更新