직선을 이루는 2점이 화면 바깥에 있는경우에는 화면끝에서 잘라줘야됩니다. 직선 클리핑은 대부분 많이 사용하는 코헨-수더랜드(Cohen-Sutherland) 알고리즘에 대해서 설명하겠습니다.이 알고리즘은 직선을 이루는 2점의 위치를 파악하여 그 점이 화면 바깥에 있을경우 직선의 기울기를 구하여 직선과 화면영역과의 교점을 구하여 화면 안쪽으로 점을 바꿔주는것입니다.
그림에서 점p1은 0x1000위치에 있고 점p2는0x0010위치에 있습니다.
점p1의 y값에 대한 화면역역의 교점은 0입니다. x값은 직선의 기울기를 구하여 화면영역의 교점을 찾습니다new_x = p1.x + -p1.y * (p2.x - p1.x) / (p2.y - p1.y ) + 0.5f현재 x위치에 x값이 교점까지 진행한 길이 만큼 더해준 것 입니다. -p1.y는 0x1000위치는 y값이 음수이기때문에 양수로 바꾼것이고 0.5를 더 한것은 new_x가 정수형이기때문에 반올림을 하기 위한 것입니다.p2도 위와 같은방법으로 구하여 주면됩니다.그리고 각각 위치에 따라 특성이 다르기때문에 switch문으로 각각의 위치에 따라 다르게 코딩을 해야합니다.
알고리즘 정리
1. 점p1, p2의 위치를 찾는다.
2. 점p1과 p2의 위치가 둘다 0x0000 이면 화면영역안에 점이 있는것이기때문에 클리핑할필요없이 함수를 빠져나간다.
3. 두 점이 둘다 화면바깥에 있고 직선이 화면영역을 걸치지 않는경우는 그릴필요가 없기때문에 함수를 빠져나간다.
4. 점p1부터 클리핑을 해준다. switch문으로 0x0001, 0x0002, 0x0004, ... 0x1010의 경우를 따로따로 구현한다.
5. 클리핑된 점을 점p1, p2에 대입한다.소스가 약간 길기 때문에 첨부된 소스를 참고하시기 바랍니다.
리얼 타임 렌더링 2판 39쪽에서 클리핑은 투영을 한 뒤, (-1 ~ +1)정규 시야 영역에서 수행한다고 나와있습니다.
그에 반해 DirectX9를 이용한 3D GAME 프로그래밍 입문 (흔히들 말씀하시는 용책) 114페이지에서는 투영 전에 절두체 평면으로 클리핑을 한다고 되어있습니다.
위가 리얼 타임 렌더링 아래가 용책입니다.
간단히 말해 "클리핑은 투영 전? 투영 후? 언제 해야 하는가?"가 궁금합니다.
제가 생각하기에는 용책에서 말한 것 과 같이 투영 전에 절두체 평면으로 잘라야 한다고 생각하는데요.
단적인 예로 위에 그림 처럼 정점 하나가 원점에 있는 삼각형 123을 클리핑하면 3이 제거 되고 (녹색으로 표시된)4, 5가 추가되야 하는데 1과 5는 카메라에서 바라보는 한 직선상에 있기 때문에 정규 시야 영역에서 x좌표가 같은 녹색 점에 있어야 합니다. 2와 4도 마찬가지고요.
하지만 투영 후 정규 시양 영역에서 잘라버리면 녹색이 아닌 빨간 점이 추가되버리거든요. (정점1, 2는 당연히 정규 시야 영역안에 있을 테고요 정점 3의 투영 전 좌표는 0, 0, 0, 1이므로 투영 후에는 0, 0, -2nf / f-n , 0 이 되니까 z축 위에 있게 됩니다)
설명하기 쉽게 점 하나가 원점에 있다고 가정했지만 굳이 원점에 있지 않아도 비슷한 오류가 생기며 이런 오류가 안 생기려면 투영 전에 클리핑을 해야 한다고 생각합니다.