이전 주제 보기 :: 다음 주제 보기 |
글쓴이 | 메시지 |
---|
[Q=kyu]
가입: 2002년 7월 11일 올린 글: 3
| openGL에서의 NDC의 z축 양의 방향이 어느쪽인지.. | 올려짐: 2002-07-29 15:32 |
| 3D game Engine Design에서 사용한 방법으로, openGL 파이프라인 상의 프로젝션 행렬을 구하고 있습니다.
그러다가 하나의 의문점이 생겼습니다. 뷰 절두체를 투영행렬을 곱하여 [-1,1]^3 이 되는 NDC를 얻게 되는데,
이 NDC 역시 오른손 좌표계로 나타내어지는 지, 즉, x축 양방향(오른쪽), y축 양방향(위쪽), z축 양방향(스크린에서 나오는 방향) 인지가 궁금합니다.
이것이 궁금한 이유는 NDC에서 [-1,1]범위 내의 Z값을 비교해서 스크린에 투영 시 먼저 뿌려야 할 것들을 판별한다고 생각하는데, glDepthFunc함수의 디폴트 옵션에서는 z값이 작을수록 화면 가까이에 있는 픽셀로 판단하기 때문입니다. 이걸 보니 NDC의 z축 양의 방향은 화면 깊이 방향인지 헥갈리네요.
glDepthFunc의 옵션으로 사용되는 인자를 보면, GL_NEVER : 항상 거짓 GL_LESS : 만일 source Z < drpth Z 라면 참 GL_EQUAL : 만일 source Z = drpth Z 라면 참 GL_LEQUAL : 만일 source Z <= drpth Z 라면 참 GL_GREATER : 만일 source Z > drpth Z 라면 참 GL_NOTEQUAL : 만일 source Z != drpth Z 라면 참 GL_GEQUAL : 만일 source Z >= drpth Z 라면 참 GL_ALWAYS : 항상 참 GL_LESS가 default로 쓰이는 인자이고, 새로 체크되는 픽셀의 z값이 더 작으면, 색상버퍼에 새로은 픽셀을 찍습니다. |
|
위로 | |
|
류광
가입: 2001년 7월 25일 올린 글: 3569 소속: GPGstudy
타 사이트 ID(?): docbook.kr::류광, indidev.net::류광 | | 올려짐: 2002-07-29 16:27 |
| NDC가 normalized device coordinates 의 약자인가요?? 어쨌든 뷰포트 변환 단계까지 도달했다면 3D는 잊어버리고(즉 Z는 버리고) '2D + 깊이'로 생각하는 것이 혼란을 피할 수 있을 것 같습니다...
OpenGL에서 깊이는 화면으로부터 화면 안쪽으로의 거리이고 범위는 [0,1]입니다. 음의 깊이에 있는 점은 그려지지 않으니까요.. 사실 깊이는 3차원 좌표계의 개념이라기보다는 은면 제거를 위한 일종의 참조 테이블이라고 보는 게 좋을 것 같아요... |
|
위로 | |
|
toki
가입: 2002년 4월 13일 올린 글: 151 소속: 대한민국
| | 올려짐: 2002-07-29 16:34 |
| 저도 항상 헷갈려 왔는데 오른손 좌표계이면 Z축이 화면 밖으로 나오는 방향인데... 그런데 projection행렬은 무조건 왼손좌표계만 사용한다고 하네요. 당연한 이야기이지만 처음에는 이 생각을 못해서, openGL이 화면 좌표계를 오른손 좌표계를 사용하더라도 projection변환이 되기전에 왼손좌표계로 변환됩니 다. 그러므로 projection에서 뽑아낸 절두체는 당연히 왼손좌표계이겠죠. |
|
위로 | |
|
류광
가입: 2001년 7월 25일 올린 글: 3569 소속: GPGstudy
타 사이트 ID(?): docbook.kr::류광, indidev.net::류광 | 제가 이해하는 방식은... | 올려짐: 2002-07-29 16:40 |
| 깊이 값이 결정되는 단계가 오면 '손잡이(handness)'성은 문제가 되지 않는다고 봅니다... (간단히 말하면 깊이값의 결정은 3D 좌표계에서 벗어나는 단계라고 보는거죠)
이 부분은 손잡이성의 문제라기보다는 그냥 화면 바깥이 양이냐 안쪽이 양이냐를 선택하는 것일 뿐이고 깊이라는 개념을 생각해 보면 당연히 화면 안쪽이 양이 되어야겠죠(수심 -10m라는 말은 없잖아요..) 화면 바깥이 양이라면 깊이 버퍼가 아니라 높이 버퍼라고 하지 않았을까 하는^^ |
|
위로 | |
|
toki
가입: 2002년 4월 13일 올린 글: 151 소속: 대한민국
| 음 똑같은 이야기 같은데요! | 올려짐: 2002-07-29 16:57 |
| projection에서는 왼손좌표계밖에 존재하지 않는다는 이야기가 깊이값이 류광님 말대로 음이 될 수 없기때문에 당연한 것이라고 생각하기 때문에 저는 별로 다를 것이 없다고 생각되어지는 데요. 그리고 질문에서 좌표계에 대한 이야기가 나왔기때문에 좌표계에 대한 것에 초점을 맞춘 대답일뿐 답하고자 한 내용자체가 다르다고는 생각하지 않습니다.
좀 오해의 소지가 있었나요 |
|
위로 | |
|
류광
가입: 2001년 7월 25일 올린 글: 3569 소속: GPGstudy
타 사이트 ID(?): docbook.kr::류광, indidev.net::류광 | | 올려짐: 2002-07-29 17:26 |
| 예 있다고 봅니다. 결과적으로는 같지만 강조하는 바가 좀 틀리지 않나 싶어서요...
toki님은 변환 과정 중 한 부분에서 좌표계가 오른손에서 왼손으로 바뀐다는 관점에서 이야기하셨구요...
제가 강조하고 싶었던 것은.... 최종 3D 변환 후 Z 좌표를 깊이로 바꾸는 과정은 좌표계 변환 차원의 문제라기보다는 참조테이블의 범위 조정 차원의 문제로 보는 게 더 이해하기 쉽지 않냐는 것이었구요... 다른 말로 하면 3D 좌표계의 손잡이성을 '2D + 깊이' 공간에 적용할 필요는 없지 않는가 하는 것이었습니다. |
|
위로 | |
|
toki
가입: 2002년 4월 13일 올린 글: 151 소속: 대한민국
| | 올려짐: 2002-07-29 21:00 |
| 제가 왼손좌표계를 말했던 것은 어차피 절두체도 기하적인 모형이기때문에 z축의 방향이 있어야 하고 그것이 왼손좌표계를 사용해야만 된다는 이야기고 좌표계가 변환되어야 한다 는 것은 openGL이 오른손 좌표계를 modelview행렬에서 사용하기때문에 변환이야기를 한 것이죠. 좌표계를 바꾼다는 이야기가 제가 하고 싶은 말의 핵심은 아니였습니다. 질문이 NDC에서 z축의 방향은? 이였기에 방향성을 정확하게 답변하고자 좌표계를 이야기했던 것이죠. 그냥 류광님 답변처럼 쉽게 깊이값이 음이 될 수 없다고 이야기를 했으면 좋았을 것 그랬네요. 다시 한번 제 관점이 좌표계가 변환된다는 이야기가 아니였다는 것을 말씀드리고 싶네요. 그래서 똑같은 이야기같은데요 라고 주장을 했던 것입니다. 의도 전달이 정확하지 않았나 보네요. 죄송 |
|
위로 | |
|
류광
가입: 2001년 7월 25일 올린 글: 3569 소속: GPGstudy
타 사이트 ID(?): docbook.kr::류광, indidev.net::류광 | | 올려짐: 2002-07-29 21:22 |
| 예.. 아무래도 제가 원래의 질문을 너무 확대해석한 게 아닌가 싶네요.. 저는 원래의 질문에 "(엔진 개발에서 OpenGL을 참고하고 있는데) OpenGL 같은 널리 쓰이는 API에서 NDC의 Z 좌표값과 깊이 테스트에 쓰이는 깊이값의 방향이 서로 다른 것은 좀 이상한 것이 아닌가?" 라는 점이 내포되어 있다고 봤거든요... 그 부분에 너무 집중하다보니 toki님의 뜻을 오해한 것 같습니다... 저야말로 죄송 |
|
위로 | |
|
Gamza
가입: 2001년 10월 11일 올린 글: 610
| 결국은... | 올려짐: 2002-07-29 21:42 |
| 결국 NDC의 Z는 화면안쪽으로 들어가는 방향이 양(+)이라는....말씀. _________________ HOME: http://www.Gamza.net |
|
위로 | |
|
류광
가입: 2001년 7월 25일 올린 글: 3569 소속: GPGstudy
타 사이트 ID(?): docbook.kr::류광, indidev.net::류광 | | 올려짐: 2002-07-29 21:53 |
| 예 어쨌든 제 뜻은 깊이값의 부호와 좌표계의 손잡이성 사이의 일치 여부가 중요하지 않다는 뜻으로 해석해 주시길... ^^;;; |
|
위로 | |
|
[Q=kyu]
가입: 2002년 7월 11일 올린 글: 3
| | 올려짐: 2002-07-29 23:53 |
| 이렇게 많은 답글을 달아주셔서 감사합니다. ^^ 재밌네요. 글 올리는거. 구글 검색하다가 첫방에 걸린 자료입니다.
http://www.cs.unc.edu/~vogel/Equations/projection.doc
이 문서에 openGL에서 사용하는 투영행렬에 관해 자세히 나와있군요. 이 글을 살펴본 결과 NDC의 z좌표는 [-1,1] 구간으로 매핑되며, 오른손 좌표계와는 반대로, 깊이방향이 z축 양의 방향이 되도록 뒤집힌다고 나옵니다.
1. The view frustum defined by the parameters (left, right, bottom, top, near, far) is mapped to the canonical view volume in (-1, 1, -1, 1, -1, 1).
2. The signs of the z-values are reversed. This is because in eyespace, the view is down the –z-axis, whereas in NDC, the view is down the +z-axis.
깊이 값이 마이너스 값에도 대응하기 때문에 투영행렬식을 이끌어 내는데 부호가 헥갈리는군요. DirectX처럼 [0,1]구간으로 대응시켰더라면, 한결 생각하기 편했을텐데 말이죠. |
|
위로 | |
|
manilee
가입: 2001년 12월 28일 올린 글: 67
타 사이트 ID(?): 156937058 | 저두 한마디 | 올려짐: 2002-07-30 09:43 |
| 일단 NDC에서의 z방향에 대해선 위에서 많이 언급되어 있는 거 같구.
다 알고 계시겠지만, 앞에서 질문하신분은 depth buffer에서의 비교 또한 궁금해 하신것 같아서, 제가 아는데까지 말씀드리겠습니다.
NDC에서 변환된 좌표는 x, y, z 모두 [-1,1] 범위를 가집니다. 이것이 바로 그냥 frame buffer에 저장되는 것이 아니고, viewport transformation에 의해 window coordinate로 전화되어서 저장됩니다. x, y는 glViewport에 의해서 frame buffer의 좌표가 정해지고(물론 full screen이 아닌 window의 경우 윈도우 기준좌표이겠지요.), z 값의 경우 glDepthRange(default는 n=0, f=1입니다.)에 의해 NDC의 z좌표를 linear mapping이 되어서 변환됩니다. glDepthRange에서는 꼭 znear<zfar일 필요는 없습니다.(뒤집어지도록 mapping할 수도 있습니다.) 식은 zw=(f-n)/2*zd+(n+f)/2
일단 변환되어진 z좌표는 [0,1]인 값으로 z-buffer에 저장됩니다.(이게 좀 애매하긴 합니다. 해서 제가 컴으로 test한 결과 f값이 1보다 크니까 변화가 없었습니다. 이런건 OpenGL spec 문서에도 언급되어 있지 않았는데, 말입니다. f가 1이하여야 한다든지 말입니다. 아니면, color값처럼 내부적으로 처리가 되든지 말입니다.) 그러니까, 8bit의 경우 unsigned integer로 [0,255]이 [0,1], 32bit의 경우 [0,65535]가 [0,1]..이런식으로 말입니다.
한가지 주의할 점은 depth range 조절로 clipping이 달라지진 않습니다. 왜냐면 앞단계에서 clipping이 일어나기 때문입니다. 단지 z-buffer에 저장할 때, depth test에 의해서 보이는 것이 달라질 수는 있어도 말입니다. 참고하시기를.. |
|
위로 | |
|
[Q=kyu]
가입: 2002년 7월 11일 올린 글: 3
| 그렇군요. | 올려짐: 2002-07-30 11:54 |
| NDC상에서 클리핑을 처리하고,
깊이 값을 glDepthRange(default는 n=0, f=1)에서 정한 범위로 선형적으로 매핑 시키고,
openGL에서 깊이버퍼의 해상도에 맞게 알아서 저장해 주고, (내부적으로 노멀라이즈를 한뒤에 깊이버퍼의 해상도를 곱해줄것 같군요.)
화면에 뿌려줄 때에는 glDepthFunc(default는 GL_LESS)에서 깊이 값이 작은 것을 위에 뿌리는 것이군요.
자세한 답변에 감사드립니다. glDepthRange라는 함수가 있었군요. |
|
위로 | |
|
류광
가입: 2001년 7월 25일 올린 글: 3569 소속: GPGstudy
타 사이트 ID(?): docbook.kr::류광, indidev.net::류광 | | 올려짐: 2002-07-30 12:08 |
| [Q=kyu] 씀: | 깊이 값이 마이너스 값에도 대응하기 때문에 투영행렬식을 이끌어 내는데 부호가 헥갈리는군요. DirectX처럼 [0,1]구간으로 대응시켰더라면, 한결 생각하기 편했을텐데 말이죠. |
NDC의 Z 좌표와 깊이 버퍼의 깊이 값을 혼동하신 게 아닐지? manilee 님 지적에서도 알 수 있듯이 깊이 값 자체는 [0, 1]로 매핑됩니다... 구체적으로는 k / (2^m -1)로 매핑됩니다. m은 깊이 버퍼의 비트 수, k는 0 ~ (2^m-1) 이구요.
앞에서도 말했듯이 모든 혼란의 원인은 깊이를 Z와 동일시 하는데 있다고 봅니다... 예를 들어 아직도 흔히 쓰이고 있는 Z 버퍼, Z 테스트라는 말은 뷰포트 변환 전과 후에 다행히 Z와 깊이의 방향이 같은 경우에만 안전하게 사용할 수 있을 뿐 그렇지 않을 경우 또는 좌표계를 의도적으로 뒤집을 수 있도록 허용하는 API의 경우에는 안전하지 못한 용어라고 봅니다.
manilee 씀: | 일단 변환되어진 z좌표는 [0,1]인 값으로 z-buffer에 저장됩니다.(이게 좀 애매하긴 합니다. 해서 제가 컴으로 test한 결과 f값이 1보다 크니까 변화가 없었습니다. 이런건 OpenGL spec 문서에도 언급되어 있지 않았는데, 말입니다. f가 1이하여야 한다든지 말입니다. 아니면, color값처럼 내부적으로 처리가 되든지 말입니다.) 그러니까, 8bit의 경우 unsigned integer로 [0,255]이 [0,1], 32bit의 경우 [0,65535]가 [0,1]..이런식으로 말입니다.
|
n과 f가 0과 1이 아닐 때에 대해서는 OpenGL 명세서의 DepthRange 항목에 나와 있는 것 같네요((1.3, 1.4 모두 섹션 2.10.1)
void DepthRange( clampd n, clampd f );
Each of n and f are clamped to lie within [0; 1], as are all arguments of type clampd or clampf.
-------
p.s 앗 Q=kyu 님 글을 남기셨네요.. 뒷북이 되었군요.. ^^ |
|
위로 | |
|
manilee
가입: 2001년 12월 28일 올린 글: 67
타 사이트 ID(?): 156937058 | 앗 그렇군요. | 올려짐: 2002-07-30 12:14 |
| 제가 꼼꼼히 OpenGL spec을. 문서를 읽지 않았네요. 한번 처음부터 끝까지 읽어 볼만한데... 시간이.. 류광님 감사 |
|
위로 | |
|
손님
| ^^ | 올려짐: 2002-07-30 16:51 |
| 와우!!! ^^ 멋지당..
1년전에 devpia에서 이 문제 나왔었는데 이제야..^^ 공론화 됐네여.. 멋진 설명과 자세한 해설 ..
그때두 이상했었는데..결국은..^^
대단하십니다..좋은설명 감사드립니다. 꾸벅.^^ |
|
위로 | |