이전 글에서 visibility와 shading 문제가 무엇인지 알아봤다. 이것을 해결하기 위해서는 광선과 물체 간에 교점을 구하고 물체의 법선 벡터를 구할 수 있어야 한다. 필자는 구, 원기둥 그리고 평면을 렌더링했는데 이 세 도형의 법선 벡터와 교점을 구하는 방법을 모두 다루지는 않을 것이다. 구와 평면의 법선 벡터와 교점은 중/고등학교 수준의 수학으로도 충분히 유도할 수 있기 때문에 이 시리즈에서는 원기둥과 광선의 교점 그리고 원기둥의 법선 벡터를 구하는 방법을 다룰 것이다. 선형대수학과 친하지 않다면 이 글을 더 읽기 전에 이 시리즈의 '선형대수' 글을 읽고 오자.
필자의 경우 옆면과 윗/아랫면을 따로 해결했다. 하나의 로직으로 교점을 찾는 방법이 있는지는 필자가 알지 못한다.
원기둥과 광선의 교점을 구하는 다양한 방법을 온라인에서 찾을 수 있다. 하지만 필자가 구현하며 찾아봤던 방법들은 직관적이지 않았고 제대로 이해하지 못한 상태에서 함부로 적용하면 버그가 발생했을 때 디버깅하기 어려울 것으로 판단했다. 그렇기에 필자 스스로 교점을 찾아낼 방법을 유도하기로 했다. 이 문제를 해결하기로 결심한 뒤 제일 처음 생각한 것은 좌표계였다. 문제를 단순화하기 위해 원기둥을 표현할 선형좌표계가 무엇이 있을지 고민했고 원기둥의 축 방향을 갖는 기저 벡터가 존재하는 좌표계에서는 원기둥이 단순해질 거라 판단했다. x,y,z 축 중 어느 축이 원기둥의 축과 일치하든 상관이 없을 것이기에 임의로 로컬 좌표계의 y축을 원기둥의 축과 일치해지도록 만들었다.
이러한 로컬 좌표계에서 원기둥은 단순히 xz 평면의 원이 y축 방향으로 무수히 존재하는 것에 불과하다.
그렇다면 원기둥의 옆면과 광선의 교점 P는 아래의 세 조건을 충족하는 점이 된다.
이 세 조건을 충족하는 점을 찾는 건 무척 단순하다. 우선 첫 번째 조건과 두 번째 조건을 충족하는 값을 구한 뒤 이 두 값을 기반으로 를 계산한다. 그 후, 의 값이 세 번째 조건을 만족하는지 체크한다.
위의 과정을 통해 로컬 좌표계에서의 교점을 구한 뒤, 행렬 변환을 통해 글로벌 좌표계로 변환시켜 주면 글로벌 좌표계에서의 원기둥과 광선의 교점이 된다. 이처럼 문제에 적합한 좌표계는 문제의 난이도를 급락시키곤 한다.
윗면과 아랫면 또한 원에 불과하다. 다만 옆면과의 교점은 원의 경계 위에 존재하지만, 윗/아랫면과 광선의 교점은 원의 경계를 포함한 원의 내부에 존재한다. 그렇기에 따로 로직을 분리할 필요가 있었다. 원기둥의 윗/아랫면과 광선의 교점 P는 아래의 세 조건을 충족하는 점이다.
광선과 원기둥의 교점이기 때문에, 윗/아랫면을 고려하든 옆면을 고려하든 0번 조건은 동일하다. 하지만 2번과 3번 조건은 조금 차이가 있는데, 2번 조건은 경계를 포함한 원의 내부에 교점이 존재하기 때문에 발생하는 조건이고 3번 조건은 윗/아랫면의 Y 좌표가 정확히 이기 때문에 발생하는 조건이다.
원기둥의 법선 벡터는 이 시리즈의 이전 글에서 설명한 원기둥 좌표계에서 무척 쉽게 구해진다. 해당 글에서, 원기둥의 법선 벡터에 해당하는 기저벡터인 을 직교좌표계의 벡터로 변환하는 방법이 담겨있으니 이를 참고하자.
다음 글에서는 교점과 법선 벡터를 사용하여 diffuse surface를 렌더링하는 방법을 다룰 것이다.