Metalでテクスチャから補正せずにサンプリングする

提供: MonoBook
ナビゲーションに移動 検索に移動

アップルが公式配布しているMetalコンピュートシェーダーを叩く超入門的なサンプルプログラム「Hello Compute」というものがある。

これはコンピュートシェーダーテクスチャを画像処理して新たなテクスチャを得て、それをフラグメントシェーダーで描画するという内容であり、いわゆるハロワに相当するものだ。

ただ、これはフラグメントシェーダーでの描画の際に画像補正がかかってしまっている。 コンピュートシェーダー部分を差し替えて色々試していたのだが、どうやっても画像が歪んでしまいバグってるのかと思ったが、よくよく考えるとフラグメントシェーダーでの描画の際に画像補正がかかってしまっているのだった。

HLSLの場合[編集 | ソースを編集]

HLSLでテクスチャサンプリングの際に画像補正したくない場合は、サンプラーの設定でMinFilterやMagFilterにPOINTを設定し、画像補正を無効化する。

    sampler Samp = sampler_state
    {
        Texture   = <Tex>;
        MinFilter = POINT;
        MagFilter = POINT;
        MipFilter = NONE;
        AddressU  = Clamp;
        AddressV  = Clamp;
    };

Metalの場合[編集 | ソースを編集]

一方、MetalのサンプラーにはMinFilterやMgFilterにPOINT相当の設定がなく、サンプラーを経由すると強制的に補正がかかってしまう。このため等倍表示であっても画像がボヤけるという欠陥がある。

     constexpr sampler textureSampler(mag_filter::linear,
                                      min_filter::linear);
     const half4 colorSample = colorTexture.sample (textureSampler, in.textureCoordinate);

これどうするんだと思ったがテクスチャにreadメソッドを発見。サンプラーを経由せずにテクスチャからピクセルを読み取ればいいようだ。

     ushort w = colorTexture.get_width();
     ushort h = colorTexture.get_height();
 
     ushort x = w * in.textureCoordinate.x ;
     ushort y = h * in.textureCoordinate.y ;
 
     const half4 colorSample = colorTexture.read(ushort2(x,y));

Metalではテクスチャのサイズをget_widthやget_heightで簡単に取得できるのでソースコードの見通しが非常によい。HLSLGLSLではいちいちユニフォーム変数などでテクスチャとは別に渡しておかねばならず非常に面倒だった点が改善されている。

関連項目[編集 | ソースを編集]