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で簡単に取得できるのでソースコードの見通しが非常によい。HLSLやGLSLではいちいちユニフォーム変数などでテクスチャとは別に渡しておかねばならず非常に面倒だった点が改善されている。