스캔 라인이있는 z- 버퍼에 대한 깊이 보간


10

내 자신의 소프트웨어 3d 래스터 라이저를 작성해야하며, 지금까지 삼각형으로 만든 3D 모델을 2D 공간으로 투영 할 수 있습니다.

점을 회전, 변환 및 투영하여 각 삼각형의 2D 공간 표현을 얻습니다. 그런 다음 3 개의 삼각형 점을 취하고 스캔 선 알고리즘 (선형 보간법 사용)을 구현하여 삼각형의 가장자리 (왼쪽 및 오른쪽)를 따라 모든 점 [x] [y]을 찾아 삼각형을 가로로 스캔 할 수 있습니다. 행 단위로 픽셀로 채 웁니다.

작동합니다. z- 버퍼링도 구현해야합니다. 이것은 삼각형의 3 개의 정점의 회전 및 변환 된 z 좌표를 알면 스캔 라인 알고리즘으로 찾은 다른 모든 점에 대해 z 좌표를 보간해야한다는 것을 의미합니다.

개념은 충분히 분명해 보입니다. 나는 먼저 다음 계산을 통해 Za와 Zb를 찾습니다.

var Z_Slope = (bottom_point_z - top_point_z) / (bottom_point_y - top_point_y);
var Za = top_point_z + ((current_point_y - top_point_y) * Z_Slope);

그런 다음 각 Zp에 대해 동일한 보간을 수평으로 수행합니다.

var Z_Slope = (right_z - left_z) / (right_x - left_x);
var Zp = left_z + ((current_point_x - left_x) * Z_Slope);

여기에 이미지 설명을 입력하십시오

현재 z가 해당 인덱스에서 이전 z보다 뷰어에 더 가까운 경우 색상을 색상 버퍼에 쓰고 새 z를 z 버퍼에 씁니다. (내 좌표계는 x : 왼쪽-> 오른쪽; y : 위쪽-> 아래쪽; z : 얼굴-> 컴퓨터 화면입니다.)

문제는, 그것은 건초로 간다는 것입니다. 프로젝트가 여기 있고 "Z-Buffered"라디오 버튼을 선택하면 결과가 표시됩니다 ... "Z-Buffered"모드에서 페인터 알고리즘을 사용하여 와이어 프레임을 그립니다. 디버깅 목적으로 )

PS : 나는 읽은 여기 당신이 자신의 역수 (의미로 Z의를 설정해야 z = 1/z당신이 보간 전). 나는 그것을 시도했지만 아무런 변화가없는 것 같습니다. 내가 무엇을 놓치고 있습니까? (누구든지 z를 1 / z로 바꾸어야하는 곳과 그것을 돌려 놓을 곳 (if)을 명확히 할 수 있습니까?)

[편집] 내가 얻는 최대 및 최소 z 값에 대한 데이터는 다음과 같습니다.

    max z: 1;                  min z: -1;                 //<-- obvious, original z of the vertices of the triangles
    max z: 7.197753398761272;  min z: 3.791703256899924;   //<-- z of the points that were drawn to screen (you know, after rotation, translation), by the scanline with zbuffer, gotten with interpolation but not 1/z.
    max z: 0.2649908532179404; min z: 0.13849507306889008;//<-- same as above except I interpolated 1/z instead of z.
//yes, I am aware that changing z to 1/z means flipping the comparison in the zBuffer check. otherwise nothing gets drawn.

어려운 디버깅에 들어가기 전에 누군가 내 개념이 올바른지 확인할 수 있습니까?

[편집 2]

z- 버퍼링을 해결했습니다. 결과적으로 도면 순서가 엉망이되지 않았습니다. z 좌표가 올바르게 계산되었습니다.

문제는 프레임 속도를 높이기 위해 화면의 실제 픽셀 대신 4 픽셀마다 4 픽셀 / 4 픽셀 상자를 그리는 것이 었습니다. 그래서 픽셀 당 16px를 그리지 만 z 버퍼 중 하나만 검사합니다. 나는 그런 가슴입니다.

TL / DR : 여전히 의문의 여지가 있습니다 : Z 대신에 Z의 역수 (1 / z에서와 같이)를 어떻게 / 왜 / 어떻게 사용해야합니까? 지금 당장은 모든 것이 작동합니다. (눈에 띄는 차이는 없습니다).


Re : "물론 현재 z가 해당 인덱스의 이전 값보다 뷰어에 더 가까운 경우 zBuffer에 추가합니다." 당신이 의미하는 방법을 말했지만 "현재 z가 색인에서 이전 z보다 뷰어에 더 가까운 경우 색상을 색상 버퍼에 쓰고 z 버퍼의 새로운 z "z 버퍼의 목적은 해당 픽셀의 색상이 카메라 눈에 더 가깝게 쓰여진 경우 색상 쓰기를 차단하는 것입니다.
Alturis

맞아요. 죄송합니다. 질문을했을 때 늦었습니다. 수정하겠습니다.
Spectraljump

답변:


5

빠른 답변 : Z는 (X ', Y')의 선형 함수는 아니지만 1 / Z는 선형 함수입니다. 선형 보간하기 때문에 1 / Z에 대해서는 올바른 결과를 얻지 만 Z에 대해서는 그렇지 않습니다.

Z1과 Z2의 비교가 정확하기 만하면 두 값이 모두 잘못되어도 zbuffer가 올바른 작업을 수행하기 때문에 알 수 없습니다. 텍스쳐 매핑을 추가 할 때 (그리고 그 질문에 답하기 위해 1 / Z, U / Z 및 V / Z를 보간하고, 다음 값에서 U와 V를 재구성 할 때 확실히 알 수 있습니다 : U = (U / Z) / (1 / Z), V = (V / Z) / (1 / Z). 나중에 감사합니다.)

예입니다. 종이를 구하십시오. 하향식보기이므로 Y 좌표를 잊어 버리십시오. X는 가로 축, Z는 세로 축, 카메라는 (0, 0)에 있으며 투영 평면은 z = 1입니다.

점 A (-2, 2)와 B (2, 4)를 고려하십시오. 세그먼트 AB의 중간 점 M은 (0, 3)입니다. 여태까지는 그런대로 잘됐다.

A를 A ': X'= X / Z = -1로 투영하므로 A '는 (-1, 1)입니다. 마찬가지로 B '는 (0.5, 1)입니다. 그러나 M의 투영은 (0, 1)이며 A'B '의 중간 점이 아닙니다. 왜? 세그먼트의 오른쪽 절반이 왼쪽 절반보다 카메라에서 더 멀기 때문에 더 작게 보입니다.

선형 보간법을 사용하여 M의 Z를 계산하려고하면 어떻게됩니까? dx = (0.5--1) = 1.5, dz = (4-2) = 2이므로 X '= 0 인 M'의 경우 선형 보간 Z는 zA + (dz / dx) (x-xA) = 2입니다. + (2 / 1.5) (0--1) = 2 + 1.333 = 3.3333-NOT 3!

왜? X '방향의 모든 단계에 대해 Z 방향으로 같은 양을 이동하지 않습니다 (즉, Z는 X'의 선형 함수가 아닙니다). 왜? 더 많이 갈수록 세그먼트가 카메라에서 멀어 지므로 한 픽셀은 공간에서 더 먼 거리를 나타냅니다.

마지막으로 대신 1 / Z를 보간하면 어떻게됩니까? 먼저 A와 B에서 1 ​​/ Z를 각각 0.5와 0.25로 계산합니다. 그런 다음 보간 : dx = (0.5--1) = 1.5, dz = (0.25-0.5) = -0.25, X '= 0에서 1 / Z = 0.5 + (-0.25 / 1.5) * (0- -1) = 0.3333. 그러나 그것은 1 / Z이므로 Z의 값은 ... 정확히 3입니다.

네, 수학은 대단합니다.


1
오, 그리고 "언제"에 관하여 : 삼각형을 래스터 화하기 시작하기 전에 (예를 들어 수직 루프 직전에) 1 / Z 값을 계산하여 스캔 라인의 왼쪽과 오른쪽에 1 / Z를 보간합니다. 이것들을 선형으로 보간하고 (1 / Z를 다시하지 마십시오-보간 된 값은 이미 1 / Z입니다!) zbuffer를 확인하기 직전에 변환을 취소하십시오.
ggambett

1
그리고 마지막으로, 왜. 평면 (삼각형이 포함 된)은 Ax + By + Cz + D = 0입니다. z는 분명히 (x, y)의 선형 함수입니다. x '= x / z 및 y'= y / z를 투영합니다. 거기에서 x = x'z와 y = y'z입니다. 원래 방정식에서 이들을 대체하면 Ax'z + By'x + Cz + D = 0이됩니다. 이제 z = -D / (Ax '+ By'+ C), 여기서 z는 선형 함수가 아님이 분명합니다. 의 (x ', y'). 그러나 1 / z는 (Ax '+ By'+ C) / -D이며 이는 (x ', y')의 선형 함수입니다.
ggambett

1
아시다시피, 나는 아주 많은 기사와 코스를 읽었으며 그 어느 것도 당신의 대답만큼 명확하지 않았습니다. 후손을 위해 "X", "Y"및 "Z"는 이미 모델에서 3D 객체의 축을 나타내는 데 사용되므로 "문자"U "및"V "는 2D 텍스처의 축을 나타냅니다. UV 텍스처링을 사용하면 3D 개체를 구성하는 다각형을 이미지의 색상으로 칠할 수 있습니다. " -Wikipedia-UV 매핑
Spectraljump

다행 이네요 사실, 전생에 컴퓨터 그래픽스를 가르쳤습니다 :)
ggambett

정말 고마워요-나는 항상 이것에 대해 궁금했습니다-그리고 더 나은 답을 찾았는지 모르겠습니다! +1
Codesmith 2013
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.