読者です 読者をやめる 読者になる 読者になる

しゅみぷろ

プログラミングとか

tex2Dでミップマップをサンプリングする際に端にノイズが出る

はじめに

f:id:es_program:20170125194724g:plain:w500

画像のような感じで、ペイント時にブラシの端にノイズが乗ることがあります。

メインテクスチャとは別の、GenerateMipMapが設定されたテクスチャをShaderで収縮し表示すると起こるようです。

解決方法をとりあえずメモしておきます。

原因

理由は詳しくわかっていませんが、原因はTextureのインポート設定でMipMapを生成していることらしく、これをOFFにすれば解決します。 以前まではtex2Dlodでパラメーターに0を設定して凌いでいたのですが、プラットフォームが限られるなどの理由から、Shader Model 3.0以降ならtex2Dlodを利用するように、それ以前ならtex2Dを利用するようにしました。

とりあえずはブラシ画像のGenerateMipMapはOFFにするように心がける必要があるので、忘れないようメモとして残しておきます。

f:id:es_program:20170125225442g:plain:w300

ちなみに、ミップマップレベルを動的に変更してチェックしたのですが、ミップマップレベルが変わった画像がペイントされているのにもかかわらず端にノイズがのっていました。

多分、追加されるミップマップの各レベルの端部分に各レベルごとの切れ目的なサムシングがあるのかなとか・・・ 暇な時にでもチェックしてみようと思います。

追記

少しだけわかったことを書いておきます。 要するに、MipMapが生成された際の画像の平均化によって、境界線付近が平均化されてしまい、それがノイズとして現れていたということになります。

詳しく解決方法を含めて纏めておきます

  • 必要ないならGenerateMipMapをOFFにしておく
  • MipMapをどうしても利用したければフィルター処理などを行わないよう設定する(MipMapを利用する時点でノイズは避けられないが軽減できる)

ミップマップによる平均化によって、境界線にぼやけた色が乗る可能性があります。これがノイズとして現れるので、ブラシ用であればMipMapはOFFでかまわないはずです。

ブラシ用にしたい画像が他のオブジェクトでも使用されている場合、パフォーマンスの観点からMipMapを利用すべきです。その場合、もう完璧にノイズを避けることは多分出来ません。しかし、ノイズを軽減する(画像によってはほぼ0になる)ことは出来ます。具体的には、BorderMipMapをONにし、FilterModeをPoint(no filter)に設定します。

BorderMipMapは、テクスチャの境界ピクセルを各ミップマップレベルへとコピー(つまり境界の色を各レベルですべて統一)します。

f:id:es_program:20170126011320g:plain:w500

FilterModeをno filterにする理由は、フィルター(ぼかし処理)をかけるとMipMapに平均化がかかるようで、これによっても境界がぼやけてしまい、それがノイズとなるためです。

で、ここまでは「MipMapを生成したりフィルター処理をかけると画像がぼやけるから、MipMap生成すると境界付近がボヤケちゃうよね」ってだけの話です。

本当の問題はここからで、このMipMapをサンプリングする際にUVは0~1が保証されているにも関わらずノイズが出ることです。 実はコレ、tex2DlodでMipMapLevelに何を指定してもノイズは出ません。つまり、ノイズの直接的な原因はtex2Dでサンプリングを行っていることです。正確に言うと、tex2Dbiasやtex2Dprojでミップマップレベルを弄っても、同様にノイズを引き起こします。

諸悪の根源はtex2Dがどのようにサンプリングを行うかに起因します。このサンプリングとMipMapとの兼ね合いによって今回のことが起こるわけですが、詳細は

あたりを見ると良さそうです。

さらに追記

シェーダーでサンプリングを行う際にtex2Dgradを用いることでノイズが出なくなりました。 この関数使ったことがなく今回のことではじめて触ってみたのですが、shader model 2.0でサポートされているのでよさそうかなと。 ただ、処理が重いのでやはりTextureのInport設定でカバーするのがよさそうです。

せっかくなのでtex2D系関数について雑にですが纏めておこうと思います。

  • tex2D
    • 指定位置のテクスチャをサンプリングする一番基本のやつ。
    • shader model 1.0
  • tex2Dproj
    • サンプリングする際に座標をw要素で除算できる。
    • shader model 2.0
  • tex2Dbias
    • サンプリングする際のミップレベルをw要素で指定出来る。
    • shader model 2.0
  • tex2Dgrad
    • ddx, ddyに与えた変化の割合に応じてサンプリングするミップレベルを変化させることが出来る。
    • vertex shaderでの利用が可能
    • shader model 2.0
  • tex2Dlod
    • サンプリングする際のミップレベルをw要素で指定出来る。
    • vertex shaderでの利用が可能
    • shader model 3.0