We will entertain your mind, enhance your brain, expand your lifestyle.

宝の地図を分割するような

1つのマテリアルで

ShaderGraphで、オブジェクトのスケールに応じて、テクスチャのオフセットを変更するシェーダーを作成した。その目的は、例えば「宝の地図を複数のパネルに分割して貼り付け、それを並べ変えるパズル」を実装すること。その実装条件は

  • パネルオブジェクトを1つ用意し、それをマトリックス状に4×4や5×5に並べる
  • パネルオブジェクトに、一つのテクスチャーを分割してオブジェクトへ貼り付ける。オブジェクトが規定の並びとなっていればテクスチャー全体が正しく表示される
  • パネルオブジェクトも、テクスチャのためのマテリアルも一つですませたい

シェーダーにテクスチャのオフセットを制御するパラメータを用意すれば、オブジェクト毎にテクスチャの表示位置を変更できるが、その場合マテリアルが複数必要となる。また、オブジェクトのUVマップをオフセットさせておけばマテリアルは一つでよいが、その場合オブジェクトがマトリックスの数だけ必要となる。

微小のスケール差で制御する

そのためシェーダを作成しようとしたが、同じオブジェクトとマテリアルでどのようにシェーダーの動きを変えるか分からなかった。

スクリプトからシェーダーパラメータは変更できるが、その場合各オブジェクト共通でマテリアルが変更されてしまう。

そこで見つけたのがグラフ内の”Object”ノード。

これは対象オブジェクトの位置とスケールがパラメータとして取り込める。位置は並べ替えで変わってしますので使用できない。残るはスケールであるが、大きく変えるとパネルの見た目が変わるので、奥行き(Z方向)に微小(4×4に分割するならば、各パネルを 1.00〜1.15倍)のスケール差とし、これをシェーダー側で利用する。

スケール=1.00の場合はオフセットは(0.0, 0.0)、スケール=1.03だとオフセット=(0.75, 0.0)、スケール=1.12だとオフセット=(0.0, 0.75)といった具合。

このシェーダーを適用したのが下図の例(宝の地図ではないが)

図では 5×5の25個のオブジェクトが並ぶが、使用しているのは丸、四角、菱形、六角形の4つのお面オブジェクト(プレハブ)で、それぞれ同じマテリアルを適用している。ぱっと見同じに見えるが、左下から右上に 1.00〜1.24倍で Z方向のスケールが変えてあり、同じテクスチャの違うオフセット位置が表示されている。

パーティクルシステムのように、オブジェクトごとに(UV値で)異なるパラメータを渡す方法があるのではと思うが、その探索はまた別途。