概要
UEでテクスチャをタイリングさせた時に、タイリングされたテクスチャの模様が並んでしまうというのをどうにかしたいといつも思います。
若干でいいのでこれをバラけさせて解消したいと思いますが、その「若干でいい」という気持ちを裏切る程度には構造が複雑で、調べるのに苦労しました。
マスクテクスチャを作ったりせず、
少ない手数でなるべく楽にできるようなシェーダーを組みました。
なお、今回のシェーダーですが、
同一テクスチャを何回も重ねて、ノイズでマスクしてタイリングが分からないようにするようなものは調べると既にたくさん出てくるので、
重ねられないテクスチャをどうバラけさせるかというのが主題です。
やりたいこと
タイリングされたUV区画ごとに位置、サイズ、回転を加えて同じ模様が並んでしまわないようにすることが目的です。
例えば、画像にあるような宝石が並んでいるようなテクスチャがあったとします。
パッと思いつくのは、回転値などを変えた同一テクスチャを2枚重ねてマスクで重ね合わせる方法ですが、
石同士が重なり合ってしまうかもしれません。それは構造的に変……
宝石はアルファチャンネルを持っており、ベーステクスチャにLerpで重ね合わせたものが下記です。
んーーーーー、超絶タイリング感すごいw
これが壁一面にあるステージだとキツイですね。
絶対修正返ってきます
このサンプルのシェーダーの作りは下記のとおりで、黄色枠で囲んだ部分が今回の目的となるシェーダーです。
このようにマテリアル関数で組んでおくと使いやすいと思います。
★マテリアル関数の中身
なんのノードを使っているのかが潰れないよう大きい画像にしています。
逆に見辛ければスミマセン…
4つの区画があり、
それぞれ
- 移動
- スケール
- 回転
- テクスチャのフチ消し対策
の調整を行っています。
カスタムコード
今回のランダム化の肝となるのが、カスタムコードのこいつです。
これは疑似乱数を出力するもので、比較的よく使われます。
各区画の赤色の濃度がそれぞれ異なっていますね。
これを強度の数値として使用します。
よく使うので、UE標準のノードとして用意してほしいところです。
Codeには
PseudoRandom(Input);
と記入します。()の中身は、Input Nameと必ず同じにしてください。
InputNameを「a」にしたなら、PseudoRandom(a); です。
より軽量版を求める方は
RandFast(Input);
というものも使用できます。
RandFastは隣同士で同濃度が続きやすい乱数のため、
今回の区画毎をランダム化させたい用途には不向きだったので使用していません。
■スケール
疑似乱数に数値をMuitiplyしているので、0でスケールのランダムが無効化されます。
大きいスケール比が入ってもかえって目立つので、実際に使用する値はせいぜい0.3程度くらいまでかなと思います。
右にある ScaleUVsByCenter で、スケールの中心点が画像の真ん中にくるようにしています。必要なければ取ってしまってOKです。
■移動
縦と横をそれぞれ変更できるように作っています。
後で回転が加わるので、縦と横を分割しなくても比較的バラついてくれますので、
より軽量を求める方はBreakOutで分けず、1Floatでシンプルな構成にしても良いと思います。
■回転
回転は数値がややこしいところなんですが、0が0°で、1で360°回転したという扱いとなります。
つまり0.25で90°回転です。
テクスチャによってはバラついた回転値が入っていると、必要な絵の端っこが切れてしまう問題が起きると思います。
StaticSwitchParameterでOn/Offスイッチを作り、どっちかにRoundを挟み込んだやつを用意することで絵が切れる問題を解消できます。
Roundで四捨五入している分、似た回転値を持つエリアは、値を切り捨てられて同じ回転値にロックされてしまう欠点がありますが、絵が切れることと比べると大した問題ではありません。
■フチ消し対策
今回のようにタイリングされたテクスチャの宿命といいますか、フチに切れ目が発生してしまうことがあります。
ここの対策は はのばさんが記載されているノードを参考に入れ込んでいます。
https://qiita.com/hannover_bloss/items/f9c2c4eb8a900e1c5bcb
あとはお好きな数値を入れてバラつかせましょう!
Inputについて
ところで、マテリアル関数のインプット項目は、黄色枠で囲った部分のチェックをONにしておきましょう。
こんな感じでなにも繋いでない場合、マテリアル関数内でInputに繋いだ数値がとりあえず出力されます。
チェックを入れてない場合、すべてのInputに何かしらの数値を繋がないとシェーダーコンパイルが通らずエラーを吐くのでちょっと面倒です。