셰이더와 GPU 파이프라인 · 레이 마칭과 거리 함수 · 실습
거리 함수로 그림자까지
목표
거리 함수만으로 형태를 정의하고, 구 추적으로 표면을 찾고, 기울기로 법선을 구해 음영과 그림자까지 넣습니다. 이 패스의 마지막 그림이 여기서 나옵니다.
왜 중요한가
래스터라이즈는 삼각형을 전제로 합니다. 형태를 바꾸려면 정점을 다시 만들어야 하고, 두 형태를 합치거나 빼는 일은 기하 연산이라 까다롭습니다. 거리 함수는 형태를 수식으로 표현합니다 — 구는 한 줄, 합집합은 min 한 줄입니다.
그리고 그 값이 안전한 전진 거리라는 성질 하나가 알고리즘 전체를 성립시킵니다. 가장 가까운 표면이 d 만큼 떨어져 있으면 어느 방향으로 가도 d 만큼은 아무것도 없으므로, 광선을 그만큼 통째로 건너뛰어도 표면을 지나칠 수 없습니다. 법선은 기울기로 구하고 그림자는 광선을 한 번 더 쏘면 됩니다. 래스터라이즈에서 별도의 자료 구조와 여러 단계가 필요하던 일들이 여기서는 같은 함수 하나로 풀립니다.
단계
1. /root/raymarch 에 도구 상자를 놓습니다.
2. /root/raymarch/sdf.py — 거리 함수와 합치기 연산.
3. /root/raymarch/march.py — 구 추적.
4. /root/raymarch/out/sphere.png — 실루엣.
5. /root/raymarch/out/shaded.png — 기울기 법선과 램버트.
6. /root/raymarch/out/csg.png — 깎고 붙인 형태.
7. /root/raymarch/out/shadow.png 와 out/07-shadow.txt — 그림자 광선.
참고
- 그림은
nohup python3 -m http.server 8080 -d /root/raymarch/out &로 띄우고 웹 미리보기 에서http://localhost:8080/을 엽니다. - 160x160 이면 광선 25,600 개입니다. 파이썬으로도 한 장에 1초 안쪽입니다 — 거리 함수가 빈 공간을 크게 건너뛰기 때문입니다.
- 흔한 실수 하나: 그림자 광선을 표면 바로 위에서 출발시키는 것입니다. 첫 걸음에 자기 자신을 맞아 모든 픽셀이 그늘이 됩니다.
- 흔한 실수 둘: 거리 함수가 실제 거리보다 큰 값을 돌려주는 것입니다. 광선이 표면을 건너뛰어 구멍이 뚫립니다.
단계 7개
- 그리기 도구 상자를 놓는다
- 거리 함수와 합치기
- 구 추적
- 실루엣부터
- 기울기로 법선을 구한다
- 형태를 깎고 붙인다
- 그림자 광선