2016-07-14 74 views
1

我写一个程序来画一条线。OpenGL - 移动摄像头时线条消失

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

有一些测试结果。

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

当z设置为20542时,该行不能被看到。

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

当z设置30321时,该行不能被看到。

等等......

代码已附上。怎么了?

P.S. 该代码是由OpenGL 1.0编写的,但是当使用OpenGL 3.0 + glm库编写代码时,仍然可以获得相同的测试结果。

#include <glut.h> 

/* 
System Info 
------------- 
OS: Win7 professional 64-bit SP1 
CPU: Intel i3-4170 @ 3.70GHz 
GPU: HD Graphics 4400 
*/ 

void display(void) { 
    // 20541 ok, 20542 not visible 
    // 30320 ok, 30321 not visible 
    const GLfloat z = 20541; 

    const GLfloat far = 1000, near = 0.1; 

    GLfloat vertices[4 * 3] = { 
     -far, -far, z - far, 
     far, far, z - far, 
    }; 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(0, 0, z, 0, 0, z - 1, 0, 1, 0); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glFrustum(-0.1, 0.1, -0.1, 0.1, near, far); 

    glColor3f(0, 1, 1); // blue 

    glBegin(GL_LINES); 
    glVertex3f(vertices[0], vertices[1], vertices[2]); 
    glVertex3f(vertices[3], vertices[4], vertices[5]); 
    glEnd(); 

    glFlush(); 
} 

int main() { 
    glutCreateWindow(""); 
    glutDisplayFunc(display); 
    glutMainLoop(); 
    return 0; 
} 
+0

我没有仔细观察,但我猜想这条线会移出“远”剪裁平面。 –

+0

您正在使用已弃用的OpenGL(自2007年起!)。 –

+0

你的'glutInit()'调用在哪里? – genpfault

回答

0

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

让我们假设一个C++实现什么样的GPU基本上没有:

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] 

正如你所看到的,bd的结果偏离数学正确结果,并略高于1.0。由于1.0以上的值在远机后面,它们被剪掉并且不可见,这正是你所拥有的行为。

+0

谢谢。你真的是一个专业人士。你所说的是OpenGL规范的一部分。 – user3181019