tex2Dでミップマップをサンプリングする際に端にノイズが出る
はじめに
画像のような感じで、ペイント時にブラシの端にノイズが乗ることがあります。
メインテクスチャとは別の、GenerateMipMapが設定されたテクスチャをShaderで収縮し表示すると起こるようです。
解決方法をとりあえずメモしておきます。
原因
理由は詳しくわかっていませんが、原因はTextureのインポート設定でMipMapを生成していることらしく、これをOFFにすれば解決します。 以前まではtex2Dlodでパラメーターに0を設定して凌いでいたのですが、プラットフォームが限られるなどの理由から、Shader Model 3.0以降ならtex2Dlodを利用するように、それ以前ならtex2Dを利用するようにしました。
とりあえずはブラシ画像のGenerateMipMapはOFFにするように心がける必要があるので、忘れないようメモとして残しておきます。
ちなみに、ミップマップレベルを動的に変更してチェックしたのですが、ミップマップレベルが変わった画像がペイントされているのにもかかわらず端にノイズがのっていました。
多分、追加されるミップマップの各レベルの端部分に各レベルごとの切れ目的なサムシングがあるのかなとか・・・ 暇な時にでもチェックしてみようと思います。
追記
少しだけわかったことを書いておきます。 要するに、MipMapが生成された際の画像の平均化によって、境界線付近が平均化されてしまい、それがノイズとして現れていたということになります。
詳しく解決方法を含めて纏めておきます
- 必要ないならGenerateMipMapをOFFにしておく
- MipMapをどうしても利用したければフィルター処理などを行わないよう設定する(MipMapを利用する時点でノイズは避けられないが軽減できる)
ミップマップによる平均化によって、境界線にぼやけた色が乗る可能性があります。これがノイズとして現れるので、ブラシ用であればMipMapはOFFでかまわないはずです。
ブラシ用にしたい画像が他のオブジェクトでも使用されている場合、パフォーマンスの観点からMipMapを利用すべきです。その場合、もう完璧にノイズを避けることは多分出来ません。しかし、ノイズを軽減する(画像によってはほぼ0になる)ことは出来ます。具体的には、BorderMipMapをONにし、FilterModeをPoint(no filter)に設定します。
BorderMipMapは、テクスチャの境界ピクセルを各ミップマップレベルへとコピー(つまり境界の色を各レベルですべて統一)します。
FilterModeをno filterにする理由は、フィルター(ぼかし処理)をかけるとMipMapに平均化がかかるようで、これによっても境界がぼやけてしまい、それがノイズとなるためです。
で、ここまでは「MipMapを生成したりフィルター処理をかけると画像がぼやけるから、MipMap生成すると境界付近がボヤケちゃうよね」ってだけの話です。
本当の問題はここからで、このMipMapをサンプリングする際にUVは0~1が保証されているにも関わらずノイズが出ることです。 実はコレ、tex2DlodでMipMapLevelに何を指定してもノイズは出ません。つまり、ノイズの直接的な原因はtex2Dでサンプリングを行っていることです。正確に言うと、tex2Dbiasやtex2Dprojでミップマップレベルを弄っても、同様にノイズを引き起こします。
諸悪の根源はtex2Dがどのようにサンプリングを行うかに起因します。このサンプリングとMipMapとの兼ね合いによって今回のことが起こるわけですが、詳細は
- Error | Unity Community
- directx - What does HLSL's tex2D return at (0,0)? - Game Development Stack Exchange
あたりを見ると良さそうです。
さらに追記
シェーダーでサンプリングを行う際にtex2Dgradを用いることでノイズが出なくなりました。 この関数使ったことがなく今回のことではじめて触ってみたのですが、shader model 2.0でサポートされているのでよさそうかなと。 ただ、処理が重いのでやはりTextureのInport設定でカバーするのがよさそうです。
せっかくなのでtex2D系関数について雑にですが纏めておこうと思います。
UnityTexturePaintがAssetStoreで公開されました
はじめに
UnityTexturePaintがAsset Storeで公開されました!
Asset Store : UnityTexturePaint
初めてのストア出品だったけど、特に滞りなく出すことができました。 Key Imageを描いてくださった@traitam様、お世話になりました。
また、ストア出展ですごく参考になった記事がありますので紹介しておきます。
さて、本エントリでは色んな方々に手軽にUnityTexturePaintを使ってもらえたら嬉しいなということで、UnityTexturePaintを使うとどんなことが出来るのかを振り返ったり考えたりしていきたいと思います。
アルゴリズムとか実現方法みたいなのはUnityTexturePaintの過去記事を参照してください。
あくまで今回は出来ることの紹介です。
UnityTexturePaintのれきし
歴史って言うほどのアレではないですが・・・
まずUnityTexturePaintって何?ってところから。
UnityTexturePaintは、ゲーム実行中にオブジェクトに色塗りをする事ができるようになるアセットです。 Asset Storeでは有料になっていますが、GitHubにてリポジトリを公開しているので、無料で使うことができます。気に入ったらAsset Storeで購入していただけると私の焼肉代になります。
UnityTexturePaintを作ろうと思ったキッカケはSplatoonでした。 なので、UnityTexturePaintは液体を塗ったような感じを出すためにはどうしたらいいのかを考えて作りました。
UnityTexturePaintを作り始めた段階の画像です。まだ塗った際にジャギーが発生したりと詰めが甘かった時期。
これが段々と改善され。。。
ジャギーを消し(左が改善前で右が改善後)。。。
質感などの品質向上など色々やってきました。。。
性能改善にも頑張って取り組みました。 キャラクターなどのモデルにも比較的軽量な計算でペイントが可能になりました。
ここまでで、私自身が考えていたUnityTexturePaintの要件を大体満たすことができました。 実は至る所にまだまだ改善の余地がありますが、ちょこちょこやっていけたらと思っています。
現在のUnityTexturePaintでできること
まずは基本の塗りについてです。
こんな風に、自由に塗ることができます。 塗る場所に質感(例えば液体とか)を与えることも出来るし、与えずにただ色だけ重ねることもできます。 塗る際に使うブラシも色も変更できます。
また、UnityTexturePaintの機能は、見方を変えればテクスチャに自由に情報を書き込めるということになります。 かなりプログラマー向けの内容になりますが、これを応用すると、例えば
こんな風に、歩いた場所を凹ませてみたり(適当な時間経過とともに凹みをもとに戻してます)
こんな近未来な床を表現したり
反射する液体を作ったり、といった事ができます。
開発中の機能
より「液体らしさ」を追求した機能として、Fluid Paintを開発しています。 この機能は、付着した液体が垂れていくような表現をさせるために使えます。
まだ未完成な部分が多いため、ちょっと時間がかかりそうです。。