← 실계산 조각
Realtime WebGL · fragment shaders · 이미지 파일 0장

코드로 그린 빛

아래 네 장면은 동영상도, 이미지도 아닙니다. 지금 이 순간 GPU가 픽셀마다 수식을 계산해서 그리는 그림입니다. 각 패널 위에 떠 있는 코드가 실제로 그 장면을 그리고 있는 셰이더의 핵심부입니다.

01LIGHTNING
float bolt(vec2 uv, float t){ float x = uv.x - 0.5; x -= (fbm(vec2(uv.y*3.5, t)) - .5) * 0.8 * (0.15 + uv.y*0.85); return 0.0035 / (abs(x)+0.0025); }
fbm 노이즈로 휘게 만든 방전 경로 · 프레임마다 재추첨
02FIRE
float n = fbm(q + vec2(0., -t*1.8)); n += 0.5*fbm(q*2.3 + vec2(t*.3, -t*3.2)); float flame = clamp( n*2.1*base - uv.y*1.15, 0., 1.); col = vec3(1.5*flame, 1.5*pow(flame,1.9), pow(flame,3.5));
5옥타브 노이즈를 위로 흘려보낸 불 · 색은 온도 램프
03BLACK HOLE
float r = length(p); float a = atan(p.y, p.x) + 0.5/(r + 0.12) - t*.1; vec2 q = vec2(cos(a), sin(a)) * r; float disk = exp(-pow((r-.42)*7., 2.));
각도를 1/r만큼 비틀어 만든 중력 렌즈 + 강착원반
04GOLD FIELD
float d1 = length(p - vec2(0., .42)); float d2 = length(p + vec2(0., .42)); float w = sin(d1*d2*16. - t*2.2 + fbm(p*2.)*1.5); float g = 0.035/(abs(w)+0.02); col = g * vec3(1., .62, .18);
두 초점 거리곱(카시니 곡선)의 등고선을 빛으로

풀고 있는 식 — 픽셀 하나에 8나노초

위 네 장면에 반복문이 안 보이는 이유는 반복이 코드가 아니라 칩 안에 있기 때문입니다. 화면은 GPU 에게 “픽셀 하나를 받으면 색 하나를 내놓는 함수”만 건네고, 나머지는 하드웨어가 200만 번 돌립니다.

색 = f(픽셀 좌표, 시간) ← 셰이더가 쓰는 함수의 전부. 이웃 픽셀을 못 본다

예산 = 1000 ms / 60 fps = 16.67 ms
1080p 픽셀 = 1920 × 1080 = 2,073,600
픽셀 하나당 = 16.67 ms / 2,073,600 = 8.04 ns3 GHz 코어라면 약 24 클럭

24 클럭이 셰이더 문법을 통째로 설명합니다. 분기(if)를 쓰면 같은 무리의 픽셀들이 서로 다른 길을 가면서 비용이 두 배가 되고, 그래서 셰이더 코드는 if 대신 곱셈으로 씁니다 — step(), smoothstep(), mix() 가 어디에나 나오는 게 그 흔적입니다. 조건을 0과 1 사이의 수로 바꿔 곱해 버리는 것이 이 예산 안에서 사는 방법입니다.

이웃을 못 본다는 제약

셰이더 함수는 자기 픽셀 좌표 말고는 아무것도 모릅니다. 옆 픽셀이 무슨 색인지, 이전 프레임이 어땠는지 볼 수 없습니다. 그래서 모든 형태를 좌표의 함수로 다시 써야 합니다 — 위 장면들의 번개도, 물결도, 도형 목록이 아니라 “이 좌표가 도형 안쪽인가”를 답하는 거리 함수로 표현돼 있습니다.

제약처럼 보이지만 이게 속도의 원천입니다. 픽셀끼리 서로를 안 보기 때문에 순서가 상관없고, 순서가 상관없으니 수천 개를 동시에 돌릴 수 있습니다. 아래 사진의 그 반복되는 블록들이 그래서 쓸모가 있습니다.

이 코드가 실제로 도는 곳

위 그림들은 전부 화면의 픽셀마다 같은 짧은 함수를 한 번씩 돌려 만든 것입니다. 그 “한 번씩”을 동시에 해내는 물건이 어떻게 생겼는지, 라이선스가 확인되는 사진으로 짚습니다.

GPU 다이를 위에서 찍은 사진. 같은 모양의 블록이 격자처럼 수없이 반복되고, 가장자리를 따라 입출력 패드가 줄지어 있다.

① 같은 것이 수없이 반복된다 — 그래서 픽셀마다 돌릴 수 있다

ATI RV670 그래픽 칩의 다이(뚜껑을 벗긴 실리콘 알맹이)입니다. 눈에 먼저 들어오는 건 같은 무늬가 계속 반복된다는 점입니다. CPU 사진처럼 서로 다른 큰 블록 몇 개가 있는 게 아니라, 거의 같은 단위가 격자로 깔려 있습니다.

이 반복이 위 그림들의 전제입니다 — 셰이더를 “픽셀 하나에 대한 함수”로만 쓰면 되는 이유가 여기 있습니다. 나머지는 저 똑같은 단위들이 서로 다른 픽셀을 맡아 동시에 처리합니다. 코드에 반복문이 안 보이는데 화면 전체가 칠해지는 건, 반복이 코드가 아니라 이 사진 안에 있기 때문입니다.

사진 Martijn Boer · 퍼블릭 도메인 · 위키미디어 커먼즈
이 화면은 이 네 종목 이야기입니다● 시세 불러오는 중

기준일을 100으로 놓고 그린 선입니다. 통화가 서로 달라 지수로 겹쳤습니다.

같은 기술의 서로 다른 칸입니다. 주가가 이 기술 때문이라고는 말하지 않습니다.