tomixy's biography

PixelGrid Inc. 2024年秋開発合宿

LT「RENDERING ENGINEへの道のり」

PixelGrid Inc. 2024年秋開発合宿

2024年秋に株式会社ピクセルグリッドで開催された開発合宿。
現地参加は叶わなかったが、開発合宿に向けて準備していたGPUレンダラーのプロトタイプについてLTを行った。

レンダリングの仕組みを追い求めて

当時、ブラウザのレンダリングエンジンの開発に惹かれていたものの、そのスケールの大きさに手も足も出せなくなっていた私は、FlutterやAndroidなど、ブラウザ以外のレンダリングエンジンの仕組みを片っ端から漁っていた。

そんな中、ZedというRust製テキストエディタの開発者ブログから、Zed内部で実装されているgpuiというGPUレンダリングライブラリのアプローチを知り、WebGPU APIとシェーダを使った高速な2Dレンダリングの実装に挑戦したいという具体的な目標にたどり着いたのだった。

SDFによるGPUレンダリング

そこでまず挑戦したのが、シェーダでのSDFを用いた矩形とテキストのレンダリング。
LTでは、その仕組みの概略を解説した。

特に、SDFテキストレンダリングは次のような手順で実装される手法で、個人的にはなかなか面白い実装経験になった。(日本語フォントに対応したいとは思わないが…)

  1. フォントファイルから各文字を取り出す
  2. 取り出した文字をテクスチャ(アトラス)に格納
  3. アトラス内の各グリフをSDF化
  4. アトラステクスチャをシェーダーに送って描画

SDFテキストレンダリングについては、より詳細に解説したページも用意している。


@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
  let g = text.glyphs[in.instance];
 
  // textureSample.a : 矩形を描画
  // textureSample.r : 文字を描画
  let distance = textureSample(atlas, atlas_sampler, in.uv).r;
 
  var width = mix(0.4, 0.1, clamp(g.font_size, 0.0, 40.0) / 40.0);
  width /= 2.0; // TODO: apply dpr
  let alpha = g.color.a * smoothstep(0.5 - width, 0.5 + width, distance);
 
  return vec4f(g.color.rgb, alpha);
}