D3DXMatrixPerspectiveFovLH function 에서 긁어 온 것이다.
(x, y, z, 1) 를 위 행렬에 w곱하면 그 결과값은
여기에 결과값의 w 에 있는 z 를 결과값 전체에 나누면, x, y 좌표는 z = 1 인 평면으로 이동된다.
그리고 z 좌표는 0~1 사이로 정규화되며, 이 값을 깊이 혹은 d 라고 부른다.
RSState 는 이 d 를 계산하고, 이 값을 가지고 OMState 에서 보간을 하고 깊이 버퍼 처리를 하고 그런다.
만약 zn 이 0 이면 문제가 발생하니 예외로 치고, 다음의 예를 하나씩 보자.
zf = 1.001, zn = 0.001,
zn 과 zf 의 가운데 값일 터였을 0.501 이 D 에서는 1에 거의 가까운 값을 갖게 된다.
zf = 4.00, zn = 2.00
위의 예보단 낫지만, Z 에서의 중앙값은 D 에서 1에 치우친 값을 갖게 된다.
이게 무슨 의미를 가질까?
z 의 값이 zf 에 가까울 수록 넓은 범위의 z 값이 d 에서는 좁은 범위에서 표현이 된다는 것.
이는 선형 보간을 하면 답이 없는 결과를 얻게 된다는 소리이다.
그런데 어떤 인간이 float 의 표현방법을 보고 새로운 보간 방법을 떠올렸다.
8 exponent bits (지수) and 26 mantissa (가수) 로 float 는 처리된다.
근데 지수와 가수를 계산한 결과 값이 아니라, 지수와 가수를 대등하게 보아서 보간할 수도 있다.
2 exponent bits and 2 mantissa 에서는 다음과 같이 된다.
(여기선 biased 방식이 아니라 그냥 양의 2진수를 생각함)
0, 1, 2, 3, 4, 6, 9
부동 소수점 계산 방식을 이해한다면, 지수부가 커질수록 정확한 수 표기가 힘들고 수 간 범위가 커짐을 알 수 있다.
이를 그래프화 한게 위 사이트의 이 그래프다.
이것만 봐서는 별 생각이 없을지도 모른다.
0~1 순서를 뒤집어보자.
우와, z 값의 내용을 선형적으로 표현할 수 있게 되었다.
그래서 가까울 때 1, 멀때를 0 으로 설정하는 z reverse 를 사용한다.
문제는 -1~1 로 범위를 설정하는 opengl 에선 편법이 필요하다는 것.
이건 적용법
https://www.gamedev.net/forums/topic/693404-reverse-depth-buffer/
댓글 없음:
댓글 쓰기