WebGLでSigned Distance Field (SDF)生成ライブラリを作ってみた
はじめに
WebGLを使って画像からSigned Distance Field (SDF)を生成するライブラリを作成しました。WebGLを内部的に使ってはいますが、高速化のためで、非WebGLアプリでも利用可能です。
SDFは文字のレンダリングや特殊効果の生成などに使われる便利なテクニックです。今回はこのライブラリの紹介と、開発中に得られた知見をお伝えします。
ライブラリの概要
- 名前: fastsdf
- 機能: アルファ付きHTMLImageElementからSDF(HTMLImageElement)を生成
- 技術: TypeScript, WebGL2
- GitHub: https://github.com/jonigata/fastsdf
基本的な使い方
npmからインストール:
npm install fastsdf
基本的な使用例:
import { generateSDF } from 'sdf-generator';
const srcImg = new Image();
srcImg.onload = () => {
const sdfImg = generateSDF(srcImg, 10 /*maxDist*/, 0.25 /*dstAlphaThreshold*/);
document.body.appendChild(sdfImg);
};
srcImg.src = 'path/to/your/image.png';
リファレンス
generateSDF(srcImg: HTMLImageElement, maxDist: number, dstAlphaThreshold: number): HTMLImageElement
Signed Distance Field画像を作ります。 出力imgのRGBは白で、Aは以下の説明のようにパラメータによって変わります。
- srcImg: 入力となるアルファ付きイメージ。アルファ以外は無視します
- maxDist: distanceを計算するときの最大距離
- dstAlphaThreshold: アルファ値の閾値(t)。出力アルファは以下のように計算されます
- tの指定がない場合
- 符号付き距離を距離を0~1に正規化した値(+maxDist→0、0→0.5、-maxDist→1.0)
- tの指定がある場合
- t < srcα: 1.0
- srcα < t: 0.0
- tの指定がない場合
- return: dstImage
出力例
上:元画像(背景が白なのでわかりづらいですが、アルファは設定されています)
下:dstImageを水色で表示して、その上に元画像を乗せたもの
コード的にはこんな感じです。
const sdf = generateSDF(img, 10, 0.25);
const canvas = document.querySelector<HTMLCanvasElement>('#canvas')!;
const ctx = canvas.getContext('2d')!;
ctx.save();
ctx.drawImage(sdf, 0, 0);
ctx.globalCompositeOperation = 'source-in';
ctx.fillStyle = 'cyan';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();
ctx.drawImage(img, 0, 0);
まとめ
GPUの並列処理能力を活用することで、高速なSDF生成が可能になりました。今後も継続的に改良を加えていく予定です。
皆さんも是非試してみてください。フィードバックお待ちしています!