2016-07-14 14 views
1

Ich schreibe ein Programm, um eine Zeile zu zeichnen.OpenGL - Zeile verschwindet beim Verschieben der Kamera

Die Linie verschwindet manchmal, wenn ich die Kamera zur positiven Z-Achse bewege (besonders wenn die Z-Achse größer als 10000 ist).

Es gibt einige Testergebnisse.

Wenn z 20541 eingestellt ist, kann die Linie gesehen werden.

Wenn z 20542 eingestellt ist, kann die Zeile NICHT gesehen werden.

Wenn z 30320 eingestellt ist, kann die Linie gesehen werden.

Wenn z 30321 eingestellt ist, kann die Zeile NICHT gesehen werden.

usw. ...

Der Code angebracht ist. Was ist los mit dir?

P.S. Der Code wird von OpenGL 1.0 geschrieben, aber ich kann immer noch das gleiche Testergebnis erhalten, wenn es von OpenGL 3.0 + GLM-Bibliothek geschrieben wird.

#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

Ich habe nicht genauer hinsehen, aber ich denke, die Linie bewegt sich aus der "far" Clipping-Ebene. –

+0

Sie verwenden veraltetes OpenGL (seit 2007!). –

+0

Wo ist dein 'glutInit()' Anruf? – genpfault

Antwort

0

Dieses Problem scheint eine numerische Instabilität der Gleitkommaarithmetik zu sein. Da Sie Punkte projizieren, die sich genau auf der fernen Ebene befinden, werden sie abgeschnitten, wenn das Fließkomma-Ergebnis ein wenig größer als das erwartete Ergebnis ist.

Lassen Sie uns eine C++ Implementierung übernehmen, was die gpu im Grunde tut:

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

Wenn nun diese Funktion mit den Werten rufen Sie stellten wir folgende Ergebnisse erhalten:

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] 

Wie Sie sehen können , weichen die Ergebnisse von b und d vom mathematisch korrekten Ergebnis ab und liegen leicht über 1,0. Da Werte über 1,0 hinter der fernen Ebene liegen, werden sie abgeschnitten und sind nicht sichtbar. Dies ist genau das Verhalten, das Sie haben.

+0

Vielen Dank. Du bist wirklich ein Profi. Was Sie gesagt haben, ist Teil der OpenGL-Spezifikation. – user3181019

Verwandte Themen