2016-07-14 3 views
1

한 줄을 그리는 프로그램을 작성했습니다.OpenGL - 카메라 이동시 줄이 사라짐

카메라가 양의 z 축 (특히 10000보다 큰 z 축)으로 이동하면 선이 때때로 사라집니다.

일부 테스트 결과가 있습니다.

z가 20541로 설정되면 줄을 볼 수 있습니다.

z가 20542로 설정되면 줄을 볼 수 없습니다.

z를 설정하면 30320이 표시됩니다.

z가 30321로 설정되면 줄을 볼 수 없습니다.

등 ...

코드가 첨부되어 있습니다. 뭐가 문제 야?

P. 코드는 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

이 문제는 부동 소수점 산술의 수치 적 불안정한 것으로 보입니다. 원거리 평면에 정확히 투영 된 점이 있기 때문에 부동 소수점 결과가 예상 결과보다 조금 클 때 클리핑됩니다.

의이 GPU는 기본적으로 무엇을의 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] 

bd의 결과는 수학적으로 정확한 결과와 다르며 1.0보다 약간 큰 값입니다. 1.0보다 큰 값은 먼 평면 뒤에 있기 때문에 멀리 떨어져서 보이지 않습니다. 이는 정확히 당신이 가진 행동입니다.

+0

감사합니다. 당신은 정말로 전문적입니다. 당신이 말한 것은 OpenGL 사양의 일부입니다. – user3181019