2016-07-14 7 views
1

Я пишу программу для рисования одной строки.OpenGL - Линия исчезает при перемещении камеры

Линия иногда исчезает, когда я перемещаю камеру на положительную ось z (особенно, когда ось z больше 10000).

Есть некоторые результаты теста.

Когда z set 20541, линия видна.

Когда z set 20542, линия НЕ МОЖЕТ быть видна.

Когда z set 30320, линия видна.

Когда z set 30321, линия НЕ МОЖЕТ быть видна.

и пр.

Код прилагается. Что не так?

P.S. Код написан OpenGL 1.0, но я все равно могу получить тот же результат теста, написанный OpenGL 3.0 + glm library.

#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 реализацию ++, что в основном делает ГПУ:

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 и d отличаются от математического правильного результата и немного превышают 1,0. Поскольку значения выше 1.0 находятся за дальним планом, они отсекаются и не видны, что является именно тем поведением, которое у вас есть.

+0

Спасибо. Вы действительно профессионал. То, что вы сказали, является частью спецификации OpenGL. – user3181019

Смежные вопросы