Hacker News

SDF vs. MSDF vs. Slug: GPU Text Rendering

SDF·MSDF·Slug 비교 — GPU 텍스트 렌더링 방식 선택하기

비트맵 아틀라스부터 SDF, MSDF, 테셀레이션, Slug까지 GPU 글꼴 렌더링 방식의 품질과 비용을 비교합니다. Slug는 글리프 외곽선을 셰이더에서 직접 처리해 크기·원근 변화와 동적 텍스트에 강하지만, 작은 글자 가독성이나 셰이더 비용 등은 실제 환경에서 따져야 합니다.

AI 요약

글자는 확대·축소하거나 원근 변환을 적용해도 선명해야 하고, 프레임마다 내용이 달라져도 빠르게 그려야 합니다. 이 글은 비트맵 텍스처 아틀라스, SDF(Signed Distance Field), MSDF(Multi-channel Signed Distance Field), 테셀레이션 기반 방식과 Slug를 비교합니다. Slug 알고리즘을 구현한 C++20 라이브러리 Slughorn도 소개합니다. 글쓴이는 Slug 특허가 2026년 3월 퍼블릭 도메인으로 공개됐다고 설명합니다.

방식별 장단점

비트맵 아틀라스는 글리프를 특정 크기로 미리 래스터화해 텍스처에 저장합니다. 구현과 이식이 쉽고 저사양 GPU에서도 잘 동작하지만, 저장한 크기보다 키우면 흐려집니다. 여러 크기와 언어를 준비할수록 텍스처 메모리가 늘어납니다.

SDF는 각 텍셀에 글자 외곽선까지의 거리를 저장합니다. 셰이더에서 거리를 기준으로 경계를 복원해 비트맵보다 넓은 크기 범위에서 선명하게 그리며, 셰이더 비용도 낮습니다. 다만 한 채널만 쓰는 SDF는 뾰족한 모서리를 부드럽게 만들어 ‘A’의 꼭짓점이나 ‘K’의 안쪽 모서리가 둥글어질 수 있습니다. MSDF는 RGB 세 채널에 서로 다른 외곽선 거리 정보를 담고, 셰이더에서 중앙값을 골라 모서리를 복원합니다. SDF보다 모서리가 잘 유지되지만, 여전히 미리 만든 아틀라스에 의존합니다. 작은 크기나 극단적인 축소에서는 품질 저하가 생기며, 세 채널을 읽는 만큼 대역폭도 더 씁니다.

테셀레이션 계열은 외곽선을 GPU가 그릴 삼각형으로 바꿉니다. Rive는 애니메이션 벡터 그래픽에 적합하고, 글에서는 초당 120프레임으로 동작하는 사례를 언급합니다. 대신 도형이 바뀌면 테셀레이션을 다시 해야 하고, 복잡한 글리프는 기하 데이터가 늘어납니다. 구현에 따라 특정 하드웨어 기능에 기대기도 합니다.

Slug가 외곽선을 처리하는 방식

Slug는 글리프의 이차 베지어 곡선과 직선 정보를 GPU 버퍼에 저장합니다. 글리프를 가로 밴드로 나누는 보조 구조를 만들어 픽셀마다 전체 외곽선을 훑지 않게 합니다. 프래그먼트 셰이더는 픽셀에서 광선을 쏘고 주변 곡선과 만나는 횟수를 세어 winding number를 구합니다. 이 값으로 글자 안팎과 픽셀의 커버리지를 판단합니다.

곡선이 만나는 끝점에서 교차를 중복 계산하거나 빠뜨리지 않도록 Lengyel의 ‘root eligibility’ 규칙을 적용합니다. 글리프를 특정 해상도로 굽지 않으므로 확대·축소와 원근 변환에 맞춰 픽셀 단위로 커버리지를 계산합니다. 글자가 프레임마다 바뀌어도 아틀라스를 다시 만들 필요가 없고, CJK처럼 글리프가 많은 언어에서도 여러 크기의 아틀라스를 쌓는 부담을 줄입니다. 글은 자유로운 카메라가 있는 3D, AR·VR, CAD 화면처럼 글자 크기와 시점을 미리 정하기 어려운 곳을 Slug의 주요 용도로 제시합니다.

비교 결과와 선택 기준

저자는 같은 글자 ‘R’을 두고 텍스처 방식은 em당 64텍셀로 맞춰 비교합니다. 정면에서는 대부분 비슷하지만, 원근 기울임에서는 비트맵이 흐려지고, 극단적으로 확대하면 SDF·MSDF가 저장된 샘플과 실제 곡선의 차이를 드러냅니다. Slug와 Rive는 실제 외곽선을 따라 확대된 경계를 표현합니다. 다만 비교표와 시각 자료는 Slughorn 제작자의 글에 실린 결과이며, 런타임 성능 수치나 다양한 환경의 독립 검증은 제시하지 않습니다.

글은 동적·대규모 글리프와 임의의 3D 시점에는 Slug, 넓은 하드웨어 지원과 사전 아틀라스가 가능한 UI에는 MSDF, 단순하고 정적인 UI에는 비트맵을 권합니다. 저사양 환경에는 SDF를, 애니메이션 벡터 그림에는 Rive 같은 테셀레이션 방식을 제안합니다. Slughorn은 FreeType·SVG·Blend2D·Cairo·Skia 입력을 지원하고 OpenGL, Vulkan, WebGPU, DirectX를 대상으로 한다고 소개합니다.

Hacker News 반응

  • @bel8 — 첫 예시에서는 제 눈에 MSDF가 Slug보다 나아 보입니다. 원근에서는 Slug가 이기는 것 같습니다. 취미용 WebGL 게임에서 MSDF로 선명한 글자를 그리고 있습니다. 시간이 나면 소스 코드와 함께 공개하고 싶습니다. 글을 공유해 줘서 고맙습니다. 나중에 더 자세히 살펴보겠습니다.
    • @Keyframe — 저도 MSDF를 씁니다. 아주 큰 텍스트 편집기를 만드는 게 아니라면, 그런 경우에도 잘 작동하고 훌륭합니다. 벡터 외곽선에서 직접 처리하는 방식은 글꼴 외곽선 파일도 배포해야 한다는 점을 고려해야 합니다. 배포 권한이 없을 수도 있습니다. MSDF 같은 아틀라스 방식은 실제 글꼴 대신 미리 렌더링한 이미지를 배포합니다.
    • @dcrazy — 렌더링된 이미지도 배포 권한이 없을 수 있습니다. 예전에 Monotype 서체를 라이선스받았는데, 입력 가능한 PDF 양식을 포함해 편집 가능한 어떤 형태로도 쓸 수 없다는 제한이 있었습니다.
  • @rezmason — Slug는 인상적입니다. 제가 가장 알려진 프로젝트는 사실상 블룸 패스가 붙은 MSDF 셰이더입니다. 지금 필요한 기능은 충분히 제공하지만, 임의의 텍스트 지원을 추가한다면 Slug를 고려하겠습니다. MSDF에서 제기하고 싶은 문제는 다들 Viktor Chlumský의 석사 논문에 나온 msdfgen을 쓰는 것 같다는 점입니다. 다른 구현도 있었으면 합니다. 그래픽 기술을 한 번만 구현한 뒤 별다른 개선 없이 모두가 쓰는 경우가 어디 있습니까? MSDF 생태계를 XKCD 2347 같은 상태에서 벗어나게 해야 합니다.
  • @flohofwoe — sokol_gfx.h 위에서 동작하는 간단한 Slug 예제를 WebGPU와 WebGL2로 만들었습니다. 내부에는 TTF를 읽고 Slug 셰이더용 곡선 데이터를 만드는 보조 코드와 stb_truetype.h, stb_ds.h가 있습니다. 이 작업은 오프라인 에셋 파이프라인 도구로 옮기는 편이 낫습니다. 예제는 커닝, 오른쪽에서 왼쪽으로 쓰는 글자, 텍스트 셰이핑을 지원하지 않습니다. Mikko Mononen의 완전한 새 텍스트 렌더링 스택 Skribidi도 있습니다. HarfBuzz, SheenBidi, libunibreak 같은 외부 의존성을 보면 국제화된 텍스트 처리가 얼마나 어려운지 알 수 있습니다.
  • @pavlov — Slug 특허를 퍼블릭 도메인으로 공개한 건 좋지만, 특허는 이미 공개한 발명에 2년 뒤 출원하는 식으로 작동하지 않습니다. 공개 전에 출원했을 것으로 추측합니다. 글에는 ‘2019년에 특허를 받았다’고 써야 합니다. AI가 쓴 글이라면 이런 일관성까지 기대하기 어려울 수도 있겠습니다.
    • @elengyel — Slug 알고리즘의 가출원은 2017년 3월 27일에 제출했고, 전체 알고리즘을 공개한 우선일이 설정됐습니다. JCGT 논문은 몇 달 뒤인 2017년 6월 14일에 나왔습니다. 정식 특허 출원은 2018년 2월 1일, 1년 기한 전에 제출했고 USPTO는 2019년 8월 6일 특허를 승인했습니다.
  • @seanw265 — 흥미롭게 읽었습니다. 저자가 ‘테셀레이션’과 ‘Rive’를 같은 뜻처럼 섞어 쓰는 부분이 헷갈립니다. Rive는 테셀레이션 방식을 사용하는 렌더러 구현이고, 일반적인 테셀레이션 방식이라면 Rive와 달리 임의 변환도 정확히 처리할 수 있지 않나요? 비교표에서 Slug가 이기거나 비기는 항목만 초록색으로 표시했는데, 공정성을 따진다면 모든 항목의 승자를 표시해야 하지 않을까요? 메모리 사용량이 낮은 Rive가 Slug의 ‘보통’보다 낫다고 볼 수도 있습니다.
  • @jayd16 — 셰이더 실행 시간 비교가 있나요? 데이터 안에서 광선을 따라가면 텍스처를 많이 읽을 것 같은데, 이를 줄이는 방법이 있는지 궁금합니다. MSDF는 목표 텍셀과 주변 샘플을 읽는 정도이고, GPU가 계산을 시작하기 전에 처리하기 쉽습니다. (M)SDF 글리프는 밉맵과도 잘 맞습니다. Slug 데이터는 압축을 풀어야 할 것 같은데, 데이터를 확대하지 않으니 문제가 안 되는 건가요?
    • @flohofwoe — Slug는 비트맵 글꼴 데이터를 쓰지 않습니다. TTF에서 미리 처리한 매개변수 조회 테이블에 가깝고, 저장 버퍼에 둡니다. WebGL처럼 저장 버퍼가 없는 환경에서는 필터링 없이 직접 조회하는 텍스처를 쓸 수도 있습니다. 픽셀 셰이더는 SDF보다 복잡합니다.
  • @YuechenLi — MSDF 아틀라스는 정적으로 굽기만 해야 하는 게 아닙니다. 필요한 글리프를 비동기적으로 아틀라스에 올리면 CJK 글리프가 많다는 문제가 꼭 큰 아틀라스를 뜻하지는 않습니다. MSDF 렌더링은 꽤 저렴하고 CPU에서도 쉽게 처리할 수 있습니다. 생성과 업로드가 글꼴·글리프별로 한 번 들 뿐입니다. 작은 글자는 일반 CPU 래스터화로 처리해도 됩니다. MSDF와 작은 글자용 래스터화를 조합하는 것보다 Slug가 얼마나 나은지 잘 모르겠습니다. 실제로 시험해 보고 싶습니다.
  • @psyclyx — Slug 특허가 퍼블릭 도메인으로 공개된 뒤 Zig 구현체 Snail을 만들었습니다. 일부 글꼴에서는 작은 글자를 보기 좋게 만들기 어려웠습니다. TrueType 글꼴은 특정 크기에서 곡선을 픽셀 격자에 맞추는 바이트코드를 담기도 합니다. 크기별 준비가 필요 없다는 Slug의 장점은 글자를 힌팅하지 않은 채 그린다는 뜻이기도 합니다. Snail은 GPU 자동 힌팅을 구현해 글리프 특징점을 미리 계산한 뒤 셰이더에서 움직입니다. 완벽하진 않고 세리프 글꼴은 특히 어렵습니다. CJK는 셰이더가 복잡해 현재는 거의 힌팅하지 않습니다.
  • @mattdesl — Fable 5가 제안한 수식에 기반해 Windfoil이라는 GPU 곡선 렌더러도 만들고 있습니다. Slug와 비슷한 점이 있지만 항상 빠르지는 않고, 셰이더 저장 공간을 덜 쓰며 픽셀 필터링에 가까운 더 높은 품질의 안티앨리어싱을 냅니다.
    • @mattdesl — Windfoil은 경계 적분으로 픽셀에 해당하는 사각 영역 안에서 winding number의 평균을 구합니다. 일반적인 글리프에서는 박스 필터를 적용한 정답을 정확히 재현합니다. 다만 평균을 구한 뒤 채우기 규칙을 적용하므로 모든 경우에 정확하지는 않습니다. 복잡하게 자기 교차하는 곡선에서는 Slug도 비슷한 오류를 낼 수 있습니다.

원문: AlphaPixel / 번역·요약: Trawling