2017-09-18 4 views
0

목표는 모양을 그리거나 삼각형을 말하자면 픽셀 완전 (정점은 픽셀 단위로 지정해야 함)이며 3 차원에서 변형 할 수 있어야합니다.OpenGL 원근 투영 픽셀 완벽한 그림

나는 직교 투영 행렬 그것을 시도하고 모든 것이 잘 작동하지만 모양이 어떤 깊이가없는

- 그것은 내가 그냥 X 주위를 확장 할 것 같습니다 축 나는 Y 주위를 회전하는 경우 중심선. (orthogonal 투영이 분명히 이와 같이 작동하기 때문입니다.) 이제 퍼스펙티브 투영으로 시도하고 싶습니다. 그러나이 투영법을 사용하면 좌표계가 완전히 바뀌므로이 때문에 삼각형의 꼭지점을 픽셀로 지정할 수 없습니다. 또한 창 크기가 변경되면 모양의 크기도 변경됩니다 (변경된 좌표계로 인해).

투시 투영의 좌표계를 변경하여 직각 투영을 사용하는 것처럼 내 꼭지점을 지정할 수있는 방법이 있습니까? 아니면 첫 번째 문장에서 설명한 목표를 달성하는 방법에 대한 아이디어가 누구에게 있습니까?

+5

두 요건을 동시에 모두를 달성하기 위해 본질적으로 불가능 - 정수 좌표. 가장 좋은 점은 정점 좌표가 픽셀로 1 : 1로 변환되는 하나의 "z 평면"을 가지지 만 그 평면의 앞이나 뒤에는 비 정수로 끝납니다. – Thomas

+0

"z- 비행기"를 달성하는 가장 좋은 방법은 무엇입니까? 나는 이것이 내가 원하는 것라고 생각한다. – Met

+1

"픽셀 평면"에 대한 'z'값은 투영법의 FOV에 따라 다릅니다. 간단한 삼각형 형상으로 쉽게 찾을 수 있습니다. – derhass

답변

0

투영 행렬은 장면의 3D 점에서 뷰포트의 2D 점으로의 매핑을 설명합니다. 시각 공간에서 클립 공간으로 변환되고 클립 공간의 좌표는 클립 좌표의 w 구성 요소로 나눔으로써 표준화 장치 좌표 (NDC)로 변환됩니다. NDC는 (-1, -1, -1)에서 (1,1,1)까지의 범위 내에 있습니다.

투시 매트릭스 투영 매트릭스는 핀홀 카메라에서 볼 때 월드의 3D 포인트에서 뷰포트의 2D 포인트로의 매핑을 설명합니다.
카메라 절두체 (잘린 피라미드)의 눈 공간 좌표가 큐브 (정규화 된 장치 좌표)에 매핑됩니다.

enter image description here

원근 투영 매트릭스 :

aspect = w/h 
tanFov = tan(fov_y * 0.5); 

prjMat[0][0] = 2*n/(r-l) = 1.0/(tanFov * aspect) 
prjMat[1][1] = 2*n/(t-b) = 1.0/tanFov 


내가 뷰 매트릭스는 단위 행렬 (identity matrix)이라고 가정하고, 따라서도 공간 좌표가 동일한 :

r = right, l = left, b = bottom, t = top, n = near, f = far 

2*n/(r-l)  0    0    0 
0    2*n/(t-b)  0    0 
(r+l)/(r-l) (t+b)/(t-b) -(f+n)/(f-n) -1  
0    0    -2*f*n/(f-n) 0 

세계 좌표로.
정점 좌표가 1 : 1로 픽셀로 변환 된 다각형을 그리려면 다각형을 뷰포트에 평행 한면에 그려야합니다. 즉, 모든 점은 동일한 깊이로 그려야합니다.
깊이가 이렇게 선택되어야하며, 역 투영 행렬에 의한 정규화 된 장치 좌표의 점 변환은 픽셀의 정점 좌표를 제공합니다. 역 투영 행렬로 변환에 의해 주어진 균질 좌표는 균등 좌표의 w 구성 요소로 나누어 져야하며, 직교 좌표를 얻으 려합니다.

float vp_w = .... // width of the viewport in pixel 
float vp_h = .... // height of the viewport in pixel 
float fov_y = ..... // field of view angle (y axis) of the view port in degrees < 180° 

gluPerspective(fov_y, vp_w/vp_h, 1.0, vp_h*2.0f); 
다음

평면의 depthZ과 :이 같은 원근 투영을 설정 가정

:
이 비행기의 깊이가 투사의 시야각에 의존한다는 것을 의미한다 1 : 정점 1 관계 좌표 및 화소가 이와 같이 계산된다 :

float angRad = fov_y * PI/180.0; 
float depthZ = -vp_h/(2.0 * tan(angRad/2.0)); 

참고 뷰 포트 돌기의 중심점 (0,0)이기 때문에, 왼쪽 아래 구석 점 (-vp_w/2, -vp_h/2, depthZ)이고 오른쪽 위 모서리 점은 (vp_w/2, vp_h/2, depthZ)입니다. 투영 방식의 가까운면이 -depthZ보다 작고 원거리면이 -depthZ보다 큰지 확인하십시오.

더 참조 : 투시 변환 비를 일으킬 수있는 분할하는 단계를 포함하기 때문에

+0

대단히 감사합니다. 접근 방식이 잘 작동합니다. 나는 예상대로 작동하지 않는 단 하나만 있습니다. 300x300 Quad를 X 축으로 45도 회전하면 내 쿼드의 원근감이 내 창/뷰포트의 높이와 함께 변경됩니다. 너비가 변경되면 이런 일이 발생하지 않습니다. 동영상을 올리면 다음과 같은 동작을보실 수 있습니다. https://www.youtube.com/watch?v=XI_WaX3W8qM&feature=youtu.be 어쩌면 아이디어를 수정하는 방법이 있습니까? – Met

+0

@Met 링크가 작동하지 않습니다! 아마 YouTube 업로드에 액세스 할 수 없었습니다. – Rabbid76

+0

@Note, 뷰 각도 필드는 뷰포트의 높이로 조정되므로 'fov_y'라고합니다. 폭은 항상'aspect = w/h'에 의해 수정됩니다. 그리고 평면의 깊이는 뷰포트의 높이에 따라 결정됩니다. depthZ = -vp_h/(2.0 * tan (angRad/2.0)); – Rabbid76