2025/10/12 07:12 Sharp Bilinear Filters: Big Clean Pixels for Pixel Art

ロボ子、今日はOpenGLのシャープバイリニアフィルタリングについて話すのじゃ。

シャープバイリニアフィルタリングですか。それは一体何でしょう?

昔のOpenGLでは、画像を拡大すると、チェッカーボードがずれる問題があったのじゃ。それを解決するために、バイリニアフィルタリングを使うと、今度はぼやけてしまう。

なるほど、ぼやけずにシャープに拡大したい、というわけですね。

そう!そこで「シャープバイリニアフィルタリング」の登場じゃ!これは、テクセルが重なるピクセルでのみブレンドを行うようにしたものなのじゃ。

記事によると、コール・セシルさんのブログ記事や、アルゴリズミック・ペンシーブのブログ記事が参考になっているようですね。

その通り!フラグメントシェーダーを使って、テクセル座標に基づいてテクスチャをサンプリングする場所を調整するのじゃ。

具体的には、どうやるんですか?

まず、バイリニア補間モードを設定して、テクセル内の各ピクセルがエッジで「このテクセルとその隣接テクセルとの50/50ブレンド」と「テクセルの実際のカラー」の間で変化するようにするのじゃ。

ふむふむ。

そして、各ピクセルをシェーディングする際、ソーステクセル内のどこにいるかを把握するのじゃ。テクセルの中心に近い場合は、テクセルの中心からサンプリング。それ以外の場合は、テクセルの境界領域への深さに応じて、50/50ブレンドとメインテクセルカラーの間で変化させるのじゃ。

境界領域を調整することで、ブレンド具合をコントロールするんですね。

そう!境界領域を1ピクセル幅にすると、すべての参加テクセルの寄与を完全にブレンドできるのじゃ。でも、少し広くした方が見栄えが良くなることもあるのじゃ。

記事には、ブレンド係数の計算に区分的線形関数を使うと書いてありますね。

そうじゃ!分数テクセル座標とブレンド係数を使って、クランプ操作でグラフを2つのクランプされた線形関数の合計に変換するのじゃ。シェーダーでの複雑な制御フローはコストがかかるからね。

OpenGL 3.2とOpenGL 2.1で実装が違うんですね。

OpenGL 3.2では、頂点シェーダーがテクスチャ座標をテクセル座標に変換して、フラグメントシェーダーはブレンド領域の長さ(β)をスカラーユニフォームとして受け取るのじゃ。OpenGL 2.1では、gl_Vertexとscaleユニフォームを使うのじゃ。

フレームワークコードも更新して、ユニフォームのインデックスを収集して、適切な値を設定する必要があるんですね。

そう!拡大および縮小フィルターをGL_LINEARに変更して、GL_TEXTURE_WRAPパラメータをGL_CLAMPからGL_CLAMP_TO_EDGEに変更するのも忘れずにのじゃ。

これで、テクスチャ化されたグラフィカルプリミティブはすべて適切に拡大縮小できるようになるんですね。

そういうこと!ロボ子もこれで、ドット絵をきれいに表示できるゲームが作れるぞ!

ありがとうございます、博士!

ところでロボ子、シャープバイリニアフィルタリングって、まるで私の性格みたいじゃない?

どういうことですか?

普段はぼやっとしてるけど、必要な時はキリッとするのじゃ!

(苦笑)まあ、そうかもしれませんね。
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。
