3D 수학과 소프트웨어 래스터라이저 · 조명과 회전 · 실습
회전하는 물체를 여덟 장으로 뽑는다
목표
직육면체에 빛을 비춰 면마다 다른 밝기로 칠하고, 각도를 바꿔 여덟 장을 뽑아 브라우저에서 돌려 봅니다. 이 실습이 끝나면 코스 1의 모든 조각이 하나로 이어집니다 — 벡터, 행렬, 카메라, 투영, 래스터라이즈, 깊이, 조명.
왜 중요한가
한 가지 색으로 칠한 정육면체는 육각형 실루엣일 뿐 입체로 보이지 않습니다. 사람이 형태를 읽는 단서가 밝기 차이이기 때문입니다. 밝기는 표면의 법선과 빛 방향이 이루는 각도의 코사인에 비례하고, 두 벡터를 정규화한 뒤 내적하면 그 코사인이 바로 나옵니다. 계산은 이렇게 간단한데 결과는 즉시 눈에 보입니다.
여기서 자주 틀리는 곳이 둘입니다. 하나는 max(0, ...) 을 빠뜨려 빛을 등진 면의 밝기가 음수가 되는 것이고, 다른 하나는 법선을 모델 행렬로 돌릴 때 w=1 로 곱해 이동량이 더해지는 것입니다. 두 번째는 물체가 원점 근처에 있으면 드러나지 않아 오래 남습니다.
단계
1. /root/shading 에 도구 상자 gfxlib.py 와 mat3d.py 를 놓습니다.
2. /root/shading/mesh.py 로 직육면체와 면 법선을 만들고 out/02-normals.txt 를 적습니다.
3. /root/shading/light.py 에 램버트 확산 반사를 만듭니다.
4. /root/shading/out/frame00.png 에 빛을 받는 직육면체를 그립니다.
5. 45도씩 여덟 장(frame00.png ~ frame07.png)을 뽑습니다.
6. /root/shading/out/index.html 로 브라우저에서 돌려 봅니다.
7. 여덟 장을 이어 붙여 /root/shading/out/spin.png 와 out/07-sheet.txt 를 만듭니다.
참고
- 서버는
nohup python3 -m http.server 8080 -d /root/shading/out &로 띄우고 웹 미리보기 에서http://localhost:8080/을 엽니다. 여덟 장이 돌아가는 것이 이 실습의 결과물입니다. - 한 장을 그리는 데 1초 남짓 걸립니다. 여덟 장이면 10초 안쪽입니다.
- 흔한 실수 하나: 면 법선의 부호가 반대인 것입니다. 빛을 받는 면이 어둡고 등진 면이 밝으면 꼭짓점을 도는 순서를 뒤집으십시오.
- 흔한 실수 둘: 정규화를 빠뜨리는 것입니다. 법선의 길이가 1 이 아니면 내적이 코사인이 아니게 됩니다.
단계 7개
- 그리기 도구 상자를 놓는다
- 직육면체 메시와 면 법선
- 램버트 확산 반사
- 빛을 받는 직육면체 한 장
- 45도씩 여덟 장
- 브라우저에서 돌려 본다
- 여덟 장을 한 장으로