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

提供: MonoBook
2019年8月28日 (水) 05:52時点における124.87.119.49 (トーク)による版 (→‎Metalの場合)
ナビゲーションに移動 検索に移動

アップルが公式配布している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ではいちいちユニフォーム変数などでテクスチャとは別に渡しておかねばならず非常に面倒だった点が改善されている。

関連項目