OpenGL - 移动相机时线条消失

时间:2016-07-14 14:20:26

标签: opengl

我写了一个程序来画一行。

当我将相机移动到正z轴时,该线有时会消失(特别是当z轴大于10000时)。

有一些测试结果。

当z设置为20541时,可以看到该行。

当z设置为20542时,无法看到该行。

当z设置为30320时,可以看到该行。

当z设置为30321时,无法看到该行。

依此类推......

附上代码。怎么了?

P.S。 代码是由OpenGL 1.0编写的,但是当我用OpenGL 3.0 + glm库编写时,我仍然能得到相同的测试结果。

SELECT DISTINCT A.ID , C.Date
FROM IDTable A
INNER JOIN AccountTable B
   ON B.AccountID = A.AccountID
INNER JOIN UserTable UT
   ON UT.UserMnemonicID = A.AssignedTo
FULL OUTER JOIN Updates U
   ON U.ID = A.ID
FULL OUTER JOIN (--  Update2, with latest date
                 select CInner.*, CMax.MaxDate
                  from Update2 CInner
                   inner join (--  Max date for every AccountID
                               select AccountID, max(Date)  MaxDate
                                from Update2
                                group by AccountID) CMax
                    on CMax.AccountID = CInner.AccountID
                     and CMax.MaxDate = CInner.Date)  C
   ON C.AccountID = B.AccountID
WHERE A.StatusID NOT IN ('Complete','Open')
   --Need help here to only return MAX date value:
   AND C.Date=(SELECT MAX(C.Date) FROM Update2)
ORDER BY A.ID

1 个答案:

答案 0 :(得分:0)

这个问题似乎是浮点运算的数值不稳定性。由于您正在投影精确位于远平面上的点,因此当浮点结果略大于预期结果时,它们会被剪切。

让我们假设一个C ++实现了gpu的基本功能:

public static string GetTimeZoneAbbreviation(DateTime time)
{
    string timeZoneAbbr;
    if(time.IsDaylightSavingTime() == true)
    {
        timeZoneAbbr = TimeZoneInfo.Local.DaylightName;
    }
    else
    {
        timeZoneAbbr = TimeZoneInfo.Local.StandardName;
    }

    return timeZoneAbbr;
}

现在使用您提供的值调用此函数时,我们得到以下结果:

glm::vec4 test_fp(float z)
{
    //Construct matrices
    auto ortho = glm::frustum(-0.1f, 0.1f, -0.1f, 0.1f, 0.1f, 1000.0f);
    auto lookat = glm::lookAt(glm::vec3(0, 0, z), glm::vec3(0, 0, z - 1.0f), glm::vec3(0, 1, 0));

    //We are only interested in the z-value
    glm::vec4 tvec(0, 0, z - 1000.0f, 1);

    //Calculate ndc vector
    auto result = ortho * lookat * tvec;

    //Homogenize
    result /= result.w;

    return result;
}

正如您所看到的,auto a = test_fp(20541.0); //< [0, 0, 1.00000000, 1] auto b = test_fp(20542.0); //< [0, 0, 1.00000191, 1] auto c = test_fp(30320.0); //< [0, 0, 1.00000000, 1] auto d = test_fp(30321.0); //< [0, 0, 1.00000191, 1] b的结果与数学正确结果不同,略高于1.0。由于大于1.0的值位于远平面后面,因此它们被剪掉并且不可见,这正是您所拥有的行为。