그림자
그림자는 물체와 광원 사이에 다른 물체가 있어 빛을 가로막거나 빛의 일부만 도달했을 때 생깁니다. 물체와 광원 사이에 다른 물체가 있는지, 있다면 얼마만큼의 빛을 가로막고 통과시키는지 알 수 있다면 그림자를 구현할 수 있습니다.
Shadow ray
색을 구하고자 하는 물체 표면의 한 점을 , 광원을 이라고 하겠습니다. 에 닿는 빛의 방향 벡터는 라 할 수 있습니다. 만약 직선 사이에 다른 물체가 있다면 빛이 에 도달하지 못하고 사이의 물체에 의해 가로막히게 됩니다. 이 때 에 그림자가 생긴다고 판정할 수 있습니다. 물체와 광원 사이에 끼인 물체가 있는지 판단하는 방법은 광선과 물체의 부딪힘 판단에서 힌트를 얻을 수 있습니다. 광선의 자취에 관한 식을 상기해 보겠습니다.
카메라의 위치 , 광선의 진행 방향 벡터 , 카메라로부터 떨어진 거리 로 이루어진 위 식은 물체와 광원 사이에 끼인 물체가 존재하는지 판단하는 방법에도 사용됩니다.
부딪힘 판단 | 그림자 | |
---|---|---|
출발점 | ||
진행방향 |
추적 역할을 했던 광선의 요소가 , 였다면 그림자의 경우 , 정규화한 벡터 이 그 역할을 담당합니다. 광선과 비슷한 요소를 갖추고 있어 이를 shadow ray 라 부릅니다. 이후 구, 원뿔, 원기둥, 평면에 대해 각각의 부딪힘을 판단하는 식을 이용해 미지수 를 구합니다.
만약 거리 가 와 광원과의 거리인 보다 작은 양수라면 와 광원사이에 물체가 있다고 할 수 있습니다. 만약 물체가 투명도 속성을 가지고 있지 않다면 의 색을 단순히 검은색으로 지정하고, 투명도가 있다면 이를 반영해 색을 계산합니다. 예를 들어 와 광원 사이에 위치한 물체의 투명도가 20%라면, 빛의 80%는 가로막히고 20%는 통과한다는 의미입니다. 따라서 Phong reflection 에 의해 계산한 의 RGB 벡터 각각의 요소에 0.2 를 곱해줍니다.
만약 여러 물체가 shadow ray 와 부딪힌다면 물체의 투명도들을 모두 곱한 결과를 이용할 수 있습니다. 예를 들어 와 광원 사이에 물체 , 가 있고 각각의 투명도가 20%, 10% 라면 20% 의 빛 중 10% 의 빛만 통과하므로 를 RGB 벡터의 각각의 요소에 곱한 결과가 점 의 색이 됩니다. shadow ray 를 이용해 그림자가 표현된 이미지를 렌더해 보겠습니다.
렌더된 결과에 전체적으로 노이즈가 있어 그림자는 커녕 물체의 색도 온전히 보이지 않습니다. 물체 표면의 점 가 부동소수점 오차로 인해 정확한 좌표 를 가리키지 않기 때문입니다.
Bias 의 필요성
위 그림과 같이 물체 위의 점 가 오차로 인해 물체의 표면보다 아주 조금 아래에 있다면 에서 출발해 광원을 향하는 shadow ray 는 출발 지점의 물체와 부딪힙니다. 이전의 렌더 결과에서 노이즈가 발생한 이유는 바로 이것 때문입니다. 물체 위의 점 를 물체 표면 조금 위의 위치로 이동시키면 이를 해결할 수 있습니다. 이동방향은 에서의 법선벡터 방향이고 이동시킨 점은 아래와 같이 쓸 수 있습니다.
이 때 Bias 는 법선벡터 방향으로의 거리이고 0.0001 과 같이 아주 작은 값으로 설정합니다. Bias 가 적용된 결과를 렌더해 보겠습니다.
Phong reflection 에 이어 그림자 역시 법선벡터를 이용해 해결할 수 있었습니다. 다음 포스트에서는 레이 트레이싱의 꽃인 반사와 굴절을 알아보겠습니다.