2016-07-14 77 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