gpt4 book ai didi

c - 来自矩阵分解的不可预测的浮点错误

转载 作者:行者123 更新时间:2023-12-01 12:16:08 25 4
gpt4 key购买 nike

我正在尝试使用以下公式分解透视矩阵的近距离和远距离:

near = m32 / (m22 - 1);
far = m32 / (m22 + 1);

这里是透视矩阵测试参数:

  aspect   = 0.782f;
fovy = glm_rad(49.984f);
nearDist = 0.1550385f;
farDist = 6000.340975f;

glm_perspective(fovy, aspect, nearDist, farDist, proj);

这里我正在做的是获取近值和远值(proj 是列主矩阵):

far  = proj[3][2] / (proj[2][2] + 1.0f);
near = proj[3][2] / (proj[2][2] - 1.0f)

结果:

near = 0.155039 
far = 5993.506348

Near 似乎可以接受,但 far 不是:/如果我对 far 使用较小的值,那么我会得到更准确的结果(正确的值是分解值):

farDist = 600.340975 (near, far): 0.155039 600.319885 
farDist = 60.340975f (near, far): 0.155039 60.340946

数学有问题吗?我有什么选择(不使用 double 来存储矩阵)?

你可以在这里看到透视矩阵公式:https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml

m22 = (near + far) / (near - far)
m32 = 2 * near * far / (near - far)

和实现(行号可能随时间变化):https://github.com/recp/cglm/blob/master/include/cglm/cam.h#L211

最佳答案

问题是 far/near 比率越大,它需要更多有效数字才能从透视矩阵中提取 far

far/near 比率增加时,m22 = (near+far)/(near-far) 变得更接近 1。

例如,使用 doublenear=0.155far=6,000,我们得到 m22 = 1.0000516680014233。当它存储为 float 时,它被截断为 1.0000516

结果的重要部分是分数。即使所有其他操作都非常准确地完成,此时您也只剩下 3 位有效数字。这与 catastrophic cancellation 非常相似.

基本上,每次 far/near 乘以 10 时都会丢失一位有效数字。当 far6,000,000 时, 的值当存储为 float 时,code>m22 将被截断为 1.0,丢失所有信息。

我试图在 Jupyter Notebook 中演示它.

但真正的问题不仅在于不可能在不损失精度的情况下提取far,而且透视矩阵本身也不准确。

如果您在 z=6,000 处获取一个 vector ,应用透视矩阵,您将不会得到 z=1.0。相反,将透视矩阵应用于 far 值不正确的 vector ,z=5993.506348 将得到 z=1.0。矩阵本身已经是错误的,所以提取 far 的方法都无济于事。

TL;DR:如果您想以合理的精度从透视矩阵中提取nearfar,您必须使用double

编辑:添加了对实际问题的解释,关于灾难性取消的原始答案只是二阶效应。

关于c - 来自矩阵分解的不可预测的浮点错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48135014/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com