OpenGL : 3D (렌더링 된) 지점이 그 앞에 다른 3D (렌더링 된) 프리미티브에 의해 폐색되는지 확인하는 방법은 무엇입니까?
문제
OpenGL 프로그램에서 나는 다음을 순서대로하고 있습니다.
// Drawing filled polyhedrons
// Drawing points using GL_POINTS
// Displaying information for each above point beside it
포인트 정보 (예 : 포인트 식별자/번호)를 표시하기 위해 포인트의 3D 좌표를 사용한 2D 창 좌표로 변환합니다. Gluproject(). 나는 2D 창 위치에 포인트 식별자를 작성합니다. Glrasterpos() 및 2D 문자 렌더링 코드.
다른 원시에 의해 렌더링 된 지점이 폐쇄되면 자동으로 ~ 아니다 OpenGL 파이프 라인에서 발생하는 자동 폐색 테스트 및 깊이 테스트로 인해 표시됩니다. 그러나이 폐색 정보를 얻지 못하므로 폐색 된 경우에도 포인트 식별자 텍스트가 포인트 옆에 표시됩니다.
3D (렌더링 된) 지점이 그 앞에 다른 3D (렌더링 된) 프리미티브에 의해 폐쇄되는지 여부를 결정하는 방법은 무엇입니까? 아니면 그 옆에 포인트 정보 텍스트를 표시하는 더 좋은 방법이 있습니까? 뿐 폐색되지 않은 경우?
참고 : 추가 렌더링 패스가 필요한 방법을 알고 있습니다. 나는 그것들이 내 목적으로 비싸다고 생각합니다.
해결책
폐색 쿼리 두 번째 패스를 기꺼이 사용하지 않으려면 z- 버퍼를 샘플링하여 테스트 포인트와 비교할 수 있습니다.
포인트 옆에 텍스트를 추가하기 때문에 포인트의 정규화 된 Z 버퍼 값 (예 : Gluproject)을 잡은 다음 해당 값을 샘플링 된 Z- 버퍼 (Glreadpixels 사용) 값과 비교하십시오. 요점이 샘플링 한 깊이 값 뒤에있는 경우 (보다 큰 경우) 포인트를 폐쇄해야하며 텍스트를 그리지 않도록 선택할 수 있습니다.
물론 이것은 텍스트 앞에 모든 지오메트리를 렌더링해야하지만 문제가되지 않아야합니다.
샘플 코드 :
// Assumed to already hold 3D coordinates of point
GLdouble point3DX, point3DY, point3DZ;
// Project 3D point coordinates to 2D
GLdouble point2DX, point2DY, point2DZ; // 2D coordinates of point
gluProject( point3DX, point3DY, point3DZ,
mMatrix, pMatrix, vMatrix, // MVP matrices
&point2DX, &point2DY, &point2DZ);
// Read depth buffer at 2D coordinates obtained from above
GLfloat bufDepth = 0.0;
glReadPixels( static_cast<GLint>( point2DX ), static_cast<GLint>( point2DY ), // Cast 2D coordinates to GLint
1, 1, // Reading one pixel
GL_DEPTH_COMPONENT, GL_FLOAT,
&bufDepth);
// Compare depth from buffer to 2D coordinate "depth"
GLdouble EPSILON = 0.0001; // Define your own epsilon
if (fabs(bufDepth - point2DZ) < EPSILON)
// 3D point is not occluded
else
// 3D point is occluded by something
다른 팁
현대 하드웨어에서는 Z- 버퍼를 읽는 것이 매우 느릴 수 있습니다. 이것이 바로 폐색 쿼리가 발명 된 이유입니다. ARB-Occlusion-Query 확장을 찾아보십시오. 결과를 얻기 전에 몇 프레임의 지연 프레임이 있지만 성능에 영향을 미치지는 않습니다.
폐색 쿼리가 어떤 이유로 든 작동하지 않으면 다음 폴백 옵션은 BSP 트리 (GL을 전혀 사용하지 않음)를 사용하여 소프트웨어 Ray-Intersect-World 작업을 수행하는 것입니다.
Alan의 답변에 따르면, 카메라 위치에서 광선을 지점까지 돌려서 수학적으로 폐색을 테스트하고 기하학이 교차하는지 여부를 결정할 수 있습니다. 인터넷에 Ray-Object 교차로 테스트를 수행하기위한 많은 참조가 있습니다 (예 : 객체/객체 교차 페이지). 지오메트리가 많으면 경계 볼륨이나 BSP 트리를 사용하여 속도를 높이고 싶을 수 있습니다.
보너스로서, 폐색 코드는 OpenGL에서 값을 추출하는 데 의존하지 않기 때문에 장치 테스트가 훨씬 쉬워야합니다.
Ashwin Nanjappa의 답변은 매우 도움이되었습니다. 나는 OpenGL 전문가가 아니기 때문에 MVP 행렬을 얻는 방법을 찾는 데 시간이 걸렸습니다. 그의 게시물을 보완하기 위해 여기에서 코드를 공유하고 있습니다.
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetIntegerv( GL_VIEWPORT, viewport );