2011-06-12 6 views
1

내 OpenGL 코드에 이상한 동작이 있습니다. 나는 바닥에 카펫을 그려 넣고 싶다.동일한 평면에있는 다른 다각형 안에있는 다각형

아래 코드에서 GROUND_SIZE가 2071보다 크고 CARPET_HEIGHT가 0.0003보다 작은 경우 작은 폴리곤이 그려지지 않습니다. 그리기 순서는 결과 이미지를 변경하지 않습니다.

#include <GL/glut.h> 

const int GROUND_SIZE = 3000; 
const bool GROUND_FIRST = true; 
const float CARPET_HEIGHT = 0.0003; 

void carpet(){ 
    glColor3f(1.0,0.0,0.0); 
    glBegin(GL_QUADS); 
     glNormal3f(0,1,0); 
     glVertex3f(-1.0, -1.0, CARPET_HEIGHT); 
     glVertex3f(1.0, -1.0, CARPET_HEIGHT); 
     glVertex3f(1.0, 1.0, CARPET_HEIGHT); 
     glVertex3f(-1.0, 1.0, CARPET_HEIGHT); 
    glEnd(); 
} 
void ground(){ 
    glColor3f(0.0,0.7,0.0); 
    glBegin(GL_QUADS); 
     glNormal3f(0,1,0); 
     glVertex3f(-GROUND_SIZE, -GROUND_SIZE, 0); 
     glVertex3f(GROUND_SIZE, -GROUND_SIZE, 0); 
     glVertex3f(GROUND_SIZE, GROUND_SIZE, 0); 
     glVertex3f(-GROUND_SIZE, GROUND_SIZE, 0); 
    glEnd(); 
} 

void draw(){ 
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    if (GROUND_FIRST) { 
     ground(); 
     carpet(); 
    } 
    else { 
     carpet(); 
     ground(); 
    } 

    glutSwapBuffers(); 
} 

int main(){ 

    int argc = 1; char* argv[] = { (char*)"" }; 
    glutInit(&argc, argv); 

    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); 
    glutInitWindowPosition(100, 50); 
    glutInitWindowSize(640, 640); 
    glutCreateWindow("Window"); 

    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    glEnable(GL_DEPTH_TEST); 

    glClearColor(0.0f, 1.0f, 1.0f, 1.0f); 

    glutDisplayFunc(draw); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(45, 1, 0.1, 1000.0); 
    gluLookAt(0.0, -5.0, 1.0, 0.0f, 0.0f, 1.0f, 0,0,1); 

    glutMainLoop(); 
    return 0; 
} 

OpenGL이 동일한 비행기의 다른 다각형 안에있는 다각형을 그리는 지 여부를 결정하는 규칙을 이해하고 싶습니다.

감사합니다.

답변

4

먼저 몇 가지 코드를 실수로 입력하십시오.

GLPROJECTION 행렬에 gluLookAt 행렬을 삽입하지 마십시오. 이것은 당신의 조명과 함께 막을 재생할 수 있습니다. gluLookAt의 행렬은 GL_MODELVIEW에 넣은 첫 번째 행렬이어야합니다.

GL_MODELVIEW 행렬을 기본 행렬로 설정하는 것도 좋은 방법입니다. 즉, GL_PROJECTION (또는 텍스처 행렬 중 하나)으로 전환하는 모든 코드는 다른 행렬을 완료 한 직후 GL_MODELVIEW로 다시 전환해야합니다.

마지막으로 항상 glClearDepth 및 glDepthFunc를 호출하는 것이 좋습니다. 디폴트 값 (1.0과 GL_LESS)은 당신이 원하는 바로 그 것이다. 그러나 이것들에 대해 명확히 밝히는 것이 항상 좋다. 그렇게하면 기본값을 사용하여 생각하는대로 사양을 검색하지 않아도됩니다.

이제 주요 문제에 대해 알아보십시오.

이 규칙은 깊이 버퍼의 규칙 일뿐입니다. 동시에 간단하고 복잡합니다.

먼저 두 평면의 기울기가 있습니다. 그들은 확실히 세계 공간에서 같은 기울기를 가지지 만, 반드시 투영 후 공간에서 같은 기울기를 가질 필요는 없습니다. 이것은 월드 공간에서 투사 후 공간으로 변환하는 다양한 계산에서의 부동 소수점 오류 때문입니다.

두 번째로, Z- 차이가 너무 작 으면, 발생할 수있는 일은 Z- 값이 적용될 수 있다는 것입니다. 또는 카펫은 부동 소수점 오류로 인해 Z 값이 더 작을 수도 있습니다.

시야각을 움직이면 카펫 플레인이 보이거나 보이지 않을 것입니다.

당신이 할 수있는 간단한 일은 항상 접지면 다음에 카펫을 그리고 glDepthFunc에 GL_LEQUAL을 사용하는 것입니다. 이는 다시 부동 소수점 오류로 인해 100 % 작동하지 않을 수 있습니다.

다음 단계는 다각형 오프셋을 사용하는 것입니다. 이것이하는 것은 프리미티브의 Z 값을 고정 값으로 바이어스하는 것입니다. 그것이 작동하는 방법의 세부 사항은 (당신이 궁금 경우는 OpenGL 사양을 확인)이 논의 너무 기술이지만, 기본적인 아이디어는 carpet 기능이 같은보고해야한다는 것입니다 :

glEnable(GL_POLYGON_OFFSET_FILL); //Activates polygon offsets for filled triangles. 
glPolygonOffset(0, 2); //The 2 is just for safety's sake; 1 ought to be enough. 
//Draw the carpet 
glDisable(GL_POLYGON_OFFSET_FILL); //Turn off polygon offsetting. 
+0

내가 보통을 설정하는 것이 좋습니다를 모든 행렬 연산 이전에 적절한 행렬 모드로 바뀌는 것입니다. – datenwolf