예제

예제

저장소에는 실행할 수 있는 예제가 36개 있습니다. 지도용 패스, ShaderToy 시절의 화면 공간 효과, 에뮬레이션 배정밀도 계열, 컴퓨트 커널 하나를 다룹니다. 그중 35개는 한 소스에서 WGSL과 GLSL ES 3.00을 모두 냅니다. 컴퓨트 커널은 GLSL ES 3.00으로 낼 버텍스나 프래그먼트 단계가 없어서 WGSL과 리플렉션만 내고, WebGL2 경로는 옵션으로 켜는 에뮬레이션입니다. 13개는 에뮬레이션 배정밀도를 씁니다. 렌더링 가능한 예제는 examples/index.ts가 내보내고, 예제 디렉터리에서 둘러볼 수 있습니다.

예제 분류 출력 설명
Graticule 지도 WGSL과 GLSL ES 3.00 지도라면 다 그리는 경위선 격자.
Hillshade 지도 WGSL과 GLSL ES 3.00 음영 기복.
fp64 deep zoom 지도 WGSL과 GLSL ES 3.00 에뮬레이션 배정밀도(f32 두 개로 만든 df64).
fp64 checker plane 지도 WGSL과 GLSL ES 3.00 월드 평면 위의 1단위 체커보드.
fp64 hyperbolic navigation 지도 WGSL과 GLSL ES 3.00 LORAN 방식의 해도 격자.
fp64 Mercator tiles 지도 WGSL과 GLSL ES 3.00 타일 엔진이 쓰는 그 계산식.
fp64 relative-to-center 지도 WGSL과 GLSL ES 3.00 행성 규모 엔진이 시점 기준으로 렌더링하는 이유.
Colour ramp 지도 WGSL과 GLSL ES 3.00 데이터로 색을 정하는 단계구분도 색상 램프.
Discard cutout 화면 공간 WGSL과 GLSL ES 3.00 가운데 원 바깥에서는 픽셀을 버리고 안쪽에서는 채움 색을 돌려주는 프래그먼트 헬퍼입니다. 프래그먼트 IO 구조체 생성자에 인자로 한 번 넣습니다.
Plasma 화면 공간 WGSL과 GLSL ES 3.00 사인파를 여러 개 더해 만든 고전 플라스마에 RGB 팔레트로 색을 입혔습니다.
Voronoi 화면 공간 WGSL과 GLSL ES 3.00 움직이는 셀룰러 노이즈.
Julia set 화면 공간 WGSL과 GLSL ES 3.00 탈출 시간으로 그리는 줄리아 프랙탈.
Mandelbrot set 화면 공간 WGSL과 GLSL ES 3.00 탈출 시간을 매끄럽게 이어 칠한 만델브로 집합.
fBm clouds 화면 공간 WGSL과 GLSL ES 3.00 프랙탈 브라운 운동.
Domain warping 화면 공간 WGSL과 GLSL ES 3.00 fbm 출력을 다시 fbm에 넣습니다.
Raymarched sphere 화면 공간 WGSL과 GLSL ES 3.00 구의 부호 있는 거리 필드입니다. 카메라 광선에서 스피어 트레이싱으로 찾고, 궤도를 도는 광원으로 블린퐁 셰이딩합니다.
Raymarched box field 화면 공간 WGSL과 GLSL ES 3.00 도메인 반복.
Tunnel 화면 공간 WGSL과 GLSL ES 3.00 데모신 시절의 터널.
Metaballs 화면 공간 WGSL과 GLSL ES 3.00 음함수로 그린 방울.
Ocean horizon 화면 공간 WGSL과 GLSL ES 3.00 원리부터 계산해 그린 바다 풍경.
Starfield 화면 공간 WGSL과 GLSL ES 3.00 텍스처 없이 그린 밤하늘.
Truchet tiles 화면 공간 WGSL과 GLSL ES 3.00 타일 하나.
Kaleidoscope 화면 공간 WGSL과 GLSL ES 3.00 극좌표로 접는 거울 반사.
Beating heart 화면 공간 WGSL과 GLSL ES 3.00 하트 곡선 (x²+y²-1)³ = x²y³입니다. 부호로 안쪽을 채우고 fwidth로 가장자리를 다듬었으며, 뾰족하게 만든 사인파 박동에 맞춰 뛰고 박자에 맞춰 빛납니다.
fp64 Mandelbrot 화면 공간 WGSL과 GLSL ES 3.00 f32 두 개로 만든 배정밀도의 고전 데모.
fp64 Julia set 화면 공간 WGSL과 GLSL ES 3.00 같은 배정밀도 기법을 줄리아 집합으로 보인 예제.
fp64 Burning Ship 화면 공간 WGSL과 GLSL ES 3.00 버닝 십 프랙탈입니다. 제곱하기 전에 |Re z|, |Im z|로 접고, 바늘처럼 뾰족한 부분을 확대합니다.
fp64 Newton fractal 화면 공간 WGSL과 GLSL ES 3.00 z³ = 1을 푸는 뉴턴 방법입니다. 색은 그 픽셀이 어느 세제곱근으로 수렴하는지 나타냅니다.
fp64 distance estimate 화면 공간 WGSL과 GLSL ES 3.00 거리 추정(d = ½·|z|·ln|z|/|dz|)으로 만델브로 경계를 그립니다. 정밀도는 식 중간에서 나눕니다.
fp64 long-uptime clock 화면 공간 WGSL과 GLSL ES 3.00 오래 켜 두면 생기는 애니메이션 버그.
fp64 catastrophic cancellation 화면 공간 WGSL과 GLSL ES 3.00 수치해석 교과서의 그 그래프를 GPU로 그립니다.
fp64 sine sweep 화면 공간 WGSL과 GLSL ES 3.00 큰 기준값에 화면에서 조금씩 움직이는 값을 더한 x로 sin(x)를 구합니다.
Gradient pass 화면 공간 WGSL과 GLSL ES 3.00 섞는 비율을 조절할 수 있는 세로 방향 두 색 그러데이션.
Specialization constant 화면 공간 WGSL과 GLSL ES 3.00 파이프라인에서 덮어쓸 수 있는 quality 상수.
2D array texture 화면 공간 WGSL과 GLSL ES 3.00 타일 아틀라스를 texture_2d_array<f32> 바인딩 하나로 씁니다.
Compute reduction 컴퓨트 WGSL @workgroup_size가 붙은 컴퓨트 커널입니다. 입력 스토리지 버퍼의 한 구간을 reduce()로 접어 출력 원소 하나로 만듭니다.

저장소를 받아 둔 디렉터리에서 실행합니다. 첫 번째 명령은 모든 예제의 WGSL, GLSL, 리플렉션을 인쇄하고, 두 번째는 id로 하나만 인쇄합니다.

Terminal window
npx tsx examples/print.ts
npx tsx examples/print.ts hillshade

gradient 패스의 GLSL ES 3.00 출력

첫 페이지에는 gradient-pass.ts의 프래그먼트 단계와 거기서 나오는 WGSL 진입점이 있습니다. 같은 함수에서 이 GLSL ES 3.00 main이 나옵니다.

void main() {
_ret = vec4(mix(u.bottom.rgb, u.top.rgb, (uv.y + u.mix_bias)), 1.0);
}

모듈 전체는 WGSL로 28줄이고, GLSL은 버텍스 단계 17줄, 프래그먼트 단계 15줄입니다. 유니폼 타입, 바이트 오프셋, 바인드 그룹 항목, 진입점 시그니처는 reflect()에서 나옵니다. reflect()는 같은 중간 표현을 읽지만 출력 경로에는 관여하지 않으므로, 호스트는 그 레이아웃대로 유니폼 버퍼를 채우면 됩니다. 검증 페이지에는 유니폼 블록의 복원된 레이아웃이 잘못 쓴 필드의 진단과 나란히 있습니다.

에뮬레이션 배정밀도

WGSL에도 GLSL ES 3.00에도 배정밀도 부동소수점은 없습니다. TypeShade는 f32 값 두 개를 합치지 않고 나란히 든 쌍으로 이를 에뮬레이션하고, 산술, 비교, 일부 내장 함수를 그 쌍에 대한 호출로 바꿔 냅니다. 그 범위 밖의 연산은 출력할 때 코드가 붙은 오류로 실패합니다. 쓰는 코드는 그대로이고 선언한 타입만 다릅니다. deep-zoom 예제에서 origin 필드는 소스에서 f64로 선언되고 유니폼 블록에서는 vec2<f32> 자리를 차지하며, 호스트가 그 자리를 분리한 쌍으로 채웁니다.

f64 산술을 하는 모듈에는 가드 텍스처 바인딩도 주입되는데, 호스트는 이 텍스처를 흰색 텍셀 하나로 채워야 합니다. GPU 드라이버의 셰이더 컴파일러는 텍셀 읽기를 미리 계산해 버릴 수 없는데, 그 읽기가 없으면 오차 보정 항을 마음대로 최적화해 없앨 수 있기 때문입니다. 연산마다 f32의 몇 배가 들므로 이 타입은 값 하나하나에 대해 골라서 씁니다. 예제는 fp64-deep-zoom.ts입니다.

같은 월드 좌표를 두 번 그렸습니다. 왼쪽은 f32, 오른쪽은 f64 (emulated)입니다. f32 쪽은 줄무늬가 계단처럼 나오는데, 이 거리에서는 f32의 ulp 하나가 줄무늬에 필요한 소수 부분보다 거칠기 때문입니다. 다른 쪽은 매끄럽게 나옵니다.

이 페이지 편집