구면 조화: 구 위의 푸리에

구면 조화 전개: 방 안의 빛을 계수 아홉 개로

영화나 게임 장면에 매끈한 회색 공을 하나 놓았다고 하자. 공의 겉 한 점이 얼마나 밝은지 알려면, 그 점이 바라보는 반구의 모든 방향에서 들어오는 빛을 비스듬한 정도에 따라 더해야 한다. 화면의 점마다 수천 방향을 더하는 일은 너무 비싸다. 거꾸로 실제 방의 빛을 재는 쪽도, 측정기를 돌려 가며 잴 수 있는 방향이 몇십 곳뿐이라 막힌다. 방향마다 다른 밝기를 숫자 몇 개로 적을 수 있다면 두 일이 모두 쉬워진다. 구면 조화가 구 위의 물결이라면, 구 위의 함수를 구면 조화 몇 개의 합으로 적을 수 있지 않을까?

역사: 흩어진 관측소에서 지구 자기장으로, 그리고 확산 조명으로

흩어진 곳에서 잰 값으로 구 위의 함수를 계수 몇 개에 담은 첫 큰 일은 지구 자기장이다. 1830년대 가우스(Carl Friedrich Gauss)와 베버(Wilhelm Weber)는 여러 나라의 관측소를 묶어 같은 시각에 자기장을 재게 했다. 가우스는 1839년 「지자기의 일반 이론」에서 자기장을 구면 조화 전개로 적고, 지도에 모인 세기·복각·편각 관측에 최소 제곱으로 맞춰 계수를 구했다. 전개는 차수 4에서 끊어, 차수 1부터 4까지 3 + 5 + 7 + 9 = 24개의 계수를 썼다. 그는 관측이 그보다 많은 항을 뒷받침하지 못한다고 보았다. 그리고 땅속에서 나오는 성분만으로 적은 전개가 관측과 잘 맞는다는 것에서 자기장의 근원이 땅속에 있다고 결론지었다. 계수 24개는 지구 자기장의 지도이자, 그 자기장이 땅속에서 온다는 증거였다.

160년쯤 뒤, 컴퓨터 그래픽에서 같은 생각이 다시 쓰였다. 라마무르티(Ravi Ramamoorthi)와 한라한(Pat Hanrahan)은 2001년 SIGGRAPH 에 「복사 조도 환경 지도의 효율적 표현(An Efficient Representation for Irradiance Environment Maps)」을 냈다. 이 논문에서 이들은 무광 물체의 밝기가 먼 곳 빛의 높은 주파수에 거의 영향을 받지 않는다는 것을 보였다. 빛의 구면 조화 계수 가운데 가장 낮은 9개만 써도 평균 오차가 약 1%라는 것이다. 9개 계수로 적은 밝기는 겉면 방향 (x, y, z)의 2차 다항식이 되므로, 화소마다 수천 방향을 더하는 대신 곱셈 몇 번으로 계산할 수 있다.

방향 30곳에서 잰 밝기를 계수 9개로

방을 하나 정한다. 바로 위에 반지름 12°로 보이는 천장 등(밝기 12), 동쪽 벽 조금 위에 반지름 25°로 보이는 창문(밝기 3), 바닥에서 올라오는 반사 0.3, 어디서나 오는 옅은 빛 0.15. 방 한가운데에 거울 공을 두면 공에 비친 모습이 그대로 「방향마다 들어오는 빛」이다. 무광 공을 두면 공의 겉 한 점은 그 점이 바라보는 반구에서 오는 빛을 비스듬한 정도(코사인)만큼 덜어 더한 밝기로 보인다. 무광 공의 밝기는 가장 밝은 곳 0.981, 가장 어두운 곳 0.282, 평균 0.536이다. 천장 등이 12였던 거울 공보다 훨씬 고르다.

이제 무광 공의 밝기를 방향 30곳에서만 쟀다고 하자. 30곳은 구 위에 고르게 퍼지도록 나선을 따라 놓았다(피보나치 나선, 무작위가 아니다). 30곳의 값으로 차수 0, 1, 2, 3까지의 구면 조화 계수를 최소 제곱으로 맞추고, 그 계수로 되살린 밝기와 참값의 차이(복원 오차)를 구 전체에서 쟀다. 오차는 평균 밝기 0.536에 대한 백분율로 적는다.

차수 몇까지 계수 수 평균 오차 (평균 밝기 대비) 가장 큰 오차
0 1 31.35% 82.9%
1 4 11.93% 37.5%
2 9 2.98% 8.9%
3 16 2.99% 9.2%

계수 1개(평균 하나)로는 31%가 어긋나고, 차수 1까지 4개면 12%, 차수 2까지 9개면 3%다. 그런데 차수 3을 더해 16개로 늘려도 3%에서 꿈쩍하지 않는다. 9개로 맞춘 계수는 차수 0이 1.8996, 차수 1이 (−0.0009, 0.3401, 0.5359), 차수 2가 (−0.0001, −0.0016, 0.1625, 0.1022, 0.1991)이다. 차수 1의 z 계수 0.3401은 위가 밝다는 것을, x 계수 0.5359는 동쪽(창문 쪽)이 밝다는 것을 말한다.

구 위의 함수를 구면 조화의 합으로 다시 적은 것을 구면 조화 전개 (방향의 함수를 계수로 다시 적기 / spherical harmonic expansion)라 한다. 계수는 푸리에 급수에서처럼 내적, 곧 함수와 기저를 곱해 구 전체에서 적분한 값이다.

f(u)=∑l=0∞ ∑m=−llalm Ylm(u),alm=∫구f(u) Ylm(u) dΩ,Elm=Hl alm\textcolor{#1b9e77}{f}(\textcolor{#a67a63}{\mathbf{u}}) = \sum_{\textcolor{#0078e1}{l}=0}^{\infty}\ \sum_{\textcolor{#0078e1}{m}=-\textcolor{#0078e1}{l}}^{\textcolor{#0078e1}{l}} \textcolor{#c45a00}{a}_{\textcolor{#0078e1}{l}\textcolor{#0078e1}{m}}\, \textcolor{#9467bd}{Y}_{\textcolor{#0078e1}{l}}^{\textcolor{#0078e1}{m}}(\textcolor{#a67a63}{\mathbf{u}}), \qquad \textcolor{#c45a00}{a}_{\textcolor{#0078e1}{l}\textcolor{#0078e1}{m}} = \int_{\text{구}} \textcolor{#1b9e77}{f}(\textcolor{#a67a63}{\mathbf{u}})\, \textcolor{#9467bd}{Y}_{\textcolor{#0078e1}{l}}^{\textcolor{#0078e1}{m}}(\textcolor{#a67a63}{\mathbf{u}})\, d\Omega, \qquad \textcolor{#1e694b}{E}_{\textcolor{#0078e1}{l}\textcolor{#0078e1}{m}} = \textcolor{#4c5d80}{H}_{\textcolor{#0078e1}{l}}\, \textcolor{#c45a00}{a}_{\textcolor{#0078e1}{l}\textcolor{#0078e1}{m}}
f(u)방향 u 에서 들어오는 빛 (거울 공에 비친 밝기)alm빛의 구면 조화 계수 (차수 l, 번호 m)Ylm구면 조화 (구 전체에서 제곱 적분이 1)dΩ구 위의 작은 넓이 (구 전체를 더하면 4π)Elm무광 공 밝기의 구면 조화 계수Hl차수별 응답: 비스듬한 정도로 덜어 더하기가 차수 l 에 곱하는 수\begin{array}{ll} \textcolor{#1b9e77}{f}(\textcolor{#a67a63}{\mathbf{u}}) & \text{방향 } \mathbf{u} \text{ 에서 들어오는 빛 (거울 공에 비친 밝기)} \\ \textcolor{#c45a00}{a}_{\textcolor{#0078e1}{l}\textcolor{#0078e1}{m}} & \text{빛의 구면 조화 계수 (차수 } l \text{, 번호 } m\text{)} \\ \textcolor{#9467bd}{Y}_{\textcolor{#0078e1}{l}}^{\textcolor{#0078e1}{m}} & \text{구면 조화 (구 전체에서 제곱 적분이 1)} \\ d\Omega & \text{구 위의 작은 넓이 (구 전체를 더하면 } 4\pi\text{)} \\ \textcolor{#1e694b}{E}_{\textcolor{#0078e1}{l}\textcolor{#0078e1}{m}} & \text{무광 공 밝기의 구면 조화 계수} \\ \textcolor{#4c5d80}{H}_{\textcolor{#0078e1}{l}} & \text{차수별 응답: 비스듬한 정도로 덜어 더하기가 차수 } l \text{ 에 곱하는 수} \end{array}

왜 무광 공은 9개로 충분하고 16개로도 나아지지 않았을까? 무광 공의 밝기는 빛 f를 「max(0, cos)」 모양의 윈도우로 덜어 더한 것이다. 구의 어느 점에서나 같은 모양의 윈도우이므로, 작은 원 평균처럼 구를 어떻게 돌려 놓고 해도 결과가 같은 연산이다. 그래서 무광 공 밝기의 계수 Eₗₘ는 빛의 계수 aₗₘ에 차수마다 정해진 수 Hₗ를 곱한 것이 된다(구면 조화 전개 식의 셋째 등식 Eₗₘ = Hₗ aₗₘ). 줄 위의 합성곱이 주파수마다 곱하기였던 것과 같은 구조다. 차수별 응답 Hₗ를 π로 나눈 값은 차수 0부터 1, 0.667, 0.250, 0, −0.042, 0, 0.016이다.

비스듬한 정도로 덜어 더하기(max(0, cos) 윈도우)가 차수 l 의 계수에 곱하는 수 Hₗ 을 π 로 나눈 값. 차수 3, 5, 7 은 0 이고, 4, 6, 8 은 0.05 보다 작다(figs.py, 식은 common.py 의 lobe_response)
비스듬한 정도로 덜어 더하기(max(0, cos) 윈도우)가 차수 l 의 계수에 곱하는 수 Hₗ 을 π 로 나눈 값. 차수 3, 5, 7 은 0 이고, 4, 6, 8 은 0.05 보다 작다(figs.py, 식은 common.py 의 lobe_response)

차수 3에는 0이 곱해지니, 계수를 16개로 늘려 차수 3을 넣어도 맞출 것이 없었다. 남은 3%는 차수 4(−0.042배)와 그 위에서 온다. 빛 f 쪽에서 보면 차수 2까지의 세기가 전체 세기의 21.9%뿐이고 나머지는 높은 차수에 흩어져 있지만, 무광 공의 밝기에서는 차수 2까지가 99.887%다. 몇 개면 되는지를 정한 것은 함수를 만든 연산이 차수마다 곱하는 수였다. 라마무르티와 한라한이 실제 환경에서 잰 빛으로 계산한 평균 오차는 약 1%였고, 이 방에서는 천장 등이 바로 위에 좁고 밝게 있어 3%쯤 나왔다.

위 왼쪽: 거울 공에 비친 빛 f 를 위도(위·수평·아래)와 방위(서·남·동·북)로 편 지도. 위 오른쪽: 무광 공의 밝기 E. 아래 왼쪽: 흰 점 30곳의 E 만으로 맞춘 계수 9개로 되살린 것. 아래 오른쪽: f 와 E 의 차수별 세기(로그 눈금)(s2_lighting.py, figs.py)
위 왼쪽: 거울 공에 비친 빛 f 를 위도(위·수평·아래)와 방위(서·남·동·북)로 편 지도. 위 오른쪽: 무광 공의 밝기 E. 아래 왼쪽: 흰 점 30곳의 E 만으로 맞춘 계수 9개로 되살린 것. 아래 오른쪽: f 와 E 의 차수별 세기(로그 눈금)(s2_lighting.py, figs.py)
직접 움직여 보기방 안의 빛을 계수 몇 개로새 창에서 열기 ↗

ML에서: 3D 가우스 스플래팅의 방향별 색

사진 수십 장으로 장면을 다시 짓는 3D 가우스 스플래팅(케르블(Bernhard Kerbl)과 동료들, 2023)은 장면을 아주 많은 작은 가우스 덩어리로 적는다. 덩어리마다 자리, 크기, 회전, 불투명도와 함께 색을 갖는데, 반짝이는 면은 보는 방향에 따라 색이 달라 보이므로 색을 방향의 함수, 곧 구면 조화 계수로 적는다. 논문은 이 방법을 「표준 관행을 따른」 것이라 적었고, 공개 코드의 기본 설정은 차수 3까지다. 덩어리 하나가 색에 숫자를 몇 개 쓰는지, 왜 학습을 차수 0부터 시작하는지는 아래 문제 6에서 따진다.

문제 4. 거울 공과 무광 공

같은 방, 같은 방향 30곳에서 이번에는 거울 공에 비친 빛(방향마다 들어오는 밝기)을 잰다. (가) 30곳 가운데 천장 등이 보이는 곳은 몇 곳인가? (나) 30곳의 값으로 차수 2 까지 계수 9개를 맞추면 평균 오차는 얼마인가? (다) 30곳 대신 구 전체에서 적분해 계수를 정확하게 구하면 나아지는가? 차수 4(25개), 8(81개)이면? (위젯 2의 「문제 4 불러오기」로 확인해 보자.)

김민준 M01
김민준

무광 공이 3%였으니까 거울 공도 비슷하겠죠. 같은 방이잖아요.

선생님 T01
선생님

30곳의 값을 먼저 봐요. 밝기 12인 곳이 몇 군데예요?

김민준 M04
김민준

하나도 없어요! 천장 등이 반지름 12°라서 30곳 사이로 빠졌어요. 창문이 보이는 곳은 한 곳이고요. 그러니 계수 9개를 맞추면 평균 오차가 76.07%예요. 등이 있는지도 모르는 거죠.

이서연 S01
이서연

(다)는 구 전체에서 정확하게 적분하면 등을 놓치지는 않아. 그런데 계수 9개로는 평균 오차가 99.63%, 25개로 99.08%, 81개로도 77.28%야. 9개로 되살린 값의 가장 큰 값이 1.529라 12짜리 등이 넓게 번진 얼룩이 돼.

선생님 T02
선생님

무광 공은 왜 9개로 됐는지 떠올려 봐요. 같은 방인데 두 공이 다른 점이 뭐죠?

이서연 S01
이서연

무광 공은 빛을 max(0, cos) 윈도우로 덜어 더한 거였죠. 그래서 높은 차수에 거의 0이 곱해져 지워졌어요.

김민준 M03
김민준

거울 공에는 그 윈도우가 없잖아.

이서연 S08
이서연

응, 빛을 그대로 비추니까 등과 창문의 날카로운 가장자리를 담은 높은 차수가 그대로 남아. 그래서 낮은 차수 몇 개로는 안 되는 거야.

김민준 M11
김민준

시험 범위를 요약 노트 한 장(낮은 차수 몇 개)으로 줄이는 건 개념 문제(무광 공)에는 통하는데, 공식 하나를 그대로 외워 써야 하는 문제(거울 공)에는 안 통하는 거랑 같네요.

문제 5. 위·아래·동·서·남·북 6곳만 재면

무광 공의 밝기를 위, 아래, 동, 서, 남, 북 여섯 방향에서만 잰다. (가) 차수 2 까지 계수 9개를 정할 수 있는가? (나) 여섯 방향에서 값이 모두 0 인 구면 조화가 있는가? 있다면 무엇인가? (다) 여섯 값으로 맞춘 계수의 평균 오차는 30곳일 때보다 얼마나 큰가? 차수 3 까지 16개로 맞추면 나아지는가? (위젯 2의 「문제 5 불러오기」로 확인해 보자.)

김민준 M01
김민준

(가)는 방정식 6개에 모르는 수 9개라 못 정해요. 그래도 컴퓨터로 최소 제곱을 돌리면 답은 나오던데요. 평균 오차 7.70%요.

선생님 T01
선생님

정하지 못한 세 수가 어디로 갔는지 봐요. 여섯 방향에서 xy는 얼마죠?

김민준 M05
김민준

위·아래는 x = y = 0, 동·서는 y = 0, 남·북은 x = 0이라 모두 0이에요. yz와 xz도 마찬가지고요. xy, yz, xz 꼴은 얼마를 더해도 여섯 값이 안 바뀌어요. 컴퓨터는 그냥 0으로 놓은 거고요.

이서연 S01
이서연

참값에서는 xz 꼴 계수가 0.099라서 0이 아니야. 그걸 못 본 데다, 차수 2의 3z² − 1 계수도 0.1808로 참값 0.1655에서 벗어났어. 높은 차수 성분이 여섯 점에서는 낮은 차수처럼 보여서 섞여 들어온 거야.

선생님 T02
선생님

그럼 계수를 16개로 늘리면 그 섞임이 풀릴까요?

김민준 M07
김민준

돌려 보니 22.97%로 오히려 세 배나 나빠졌어요. 숫자 6개로 16개를 정하라니까 엉뚱한 값을 지어내네요.

이서연 S11
이서연

샘플링할 때 칸이 성기면 빠른 물결이 느린 물결로 보이던 에일리어싱이랑 같아. 구에서는 「몇 곳에서 쟀나」가 「몇 차수까지 믿을 수 있나」를 정하는 거고. 30곳이면 9개를 넉넉히 정할 수 있었어.

문제 6. 가우스 덩어리 하나의 색 숫자

3D 가우스 스플래팅은 덩어리마다 빨강·초록·파랑 세 채널의 색을 각각 차수 3 까지의 구면 조화 계수로 적는다. (가) 한 채널에 계수가 몇 개이고, 덩어리 하나의 색 숫자는 모두 몇 개인가? (나) 색 말고 자리 3, 크기 3, 회전(사원수) 4, 불투명도 1 개를 더 가진다. 덩어리 하나의 숫자 가운데 색이 차지하는 비율은? 덩어리 100만 개를 32비트 실수로 저장하면 색에 몇 MB 가 드는가? 차수 0 만 쓰면? (다) 원 논문은 학습을 차수 0 계수만으로 시작하고, 1000번 반복마다 차수를 하나씩 더해 차수 3 까지 늘렸다. 왜 처음부터 차수 3 을 다 쓰지 않았을까?

김민준 M01
김민준

(가)는 차수 0, 1, 2, 3이니까 1 + 3 + 5 + 7 = 16개, 세 채널이면 48개요. (나)는 색 아닌 게 11개라 모두 59개, 색이 81.4%예요. 100만 개면 색만 192 MB, 차수 0이면 12 MB요. 저장 공간 대부분이 색이네요.

이서연 S01
이서연

(다)는 학습을 빨리 하려고 그런 거 아닐까? 처음엔 적은 숫자로 대충 맞추고.

선생님 T01
선생님

방 구석을 찍거나 방 안에서 바깥쪽으로 둘러 찍으면, 덩어리 하나를 비추는 사진의 방향이 한쪽에 몰려요. 논문은 그런 장면에서 차수 0 성분이 아예 틀린 값으로 간다고 적었어요.

이서연 S06
이서연

아, 덩어리 하나를 비추는 방향이 한쪽에만 있으면 문제 5의 여섯 방향과 같은 처지예요.

선생님 T01
선생님

문제 5에서 숫자 몇 개로 계수 16개를 맞추면 어떻게 됐죠?

이서연 S07
이서연

엉뚱한 값을 지어냈어요. 그게 평균 색인 차수 0까지 끌고 가는 거네요.

김민준 M01
김민준

그래서 평균 색부터 정하고 차수를 하나씩 연 거구나.

선생님 T13
선생님

그래요. 논문은 이것을 「각도 정보가 모자라면 계수 학습이 흔들린다」고 적었어요. 낮은 차수부터 여는 일정은 잰 방향 수보다 많은 계수를 한꺼번에 믿지 않게 하는 장치예요.

김민준 M11
김민준

조별 과제도 주제부터 정하고 세부 역할을 나눠야지, 처음부터 다 정하면 엉망이 되더라고요.