以下のように通常のマテリアルだとオブジェクトスケールによって表示されるテクスチャのサイズが異なってしまいます。
これを以下のようにどんな大きさのオブジェクトに適用しても同じスケールのテクスチャで表示されるようにしてみたのでその内容をメモしておきます。
数学的な素養があまりないのでツッコミがあったらお願いします。
UE4.25.4で実装しています。
既存の解決方法とその課題
以下のサイトにあるようにAbsolute World Positionを利用することでオブジェクトスケールと関係なく表示できるようになります。
【CG】テクスチャをオブジェクトスケール等を無視して、UV値のみに依存させる【UE4】 – 建築グラビア
ただし、上記に紹介されている方法だとXY平面、YZ平面、ZX平面から斜めになると表示がずれてしまいます。
オブジェクトスケールに依存しないマテリアル
面が斜めになっても大丈夫なようなマテリアルを作ってみました。
考え方
以下の図のように下記2つの交点が求まれば原点とあわせて距離を求めてU、Vの値が出せるのでその値を使ってみます。
- 法線に対する平面とWorldPositionから法線のXY成分ベクトルとの交点
- 法線に対する平面とXY平面の接線と上記交点との最短距離の交点
ちなみに法線がZ軸方向に完全に上向きと下向きの場合は上記の計算ができないのでWorldPositionのXY成分をUV値とします。
マテリアルファンクション - MF_IntersectionOfLineAndPlane
原点からの法線Normalで表される平面と位置LinePointからベクトルLineVectorで表される直線との交点を求める関数。
数式としてはこちらのサイトを参照。
マテリアルファンクション - MF_ShortestIntersectionOfVectorAndPoint
原点を通りベクトルVectorと地点Pointとの最短の交点を求める関数。
数式としてはこちらのサイトを参照。
マテリアルファンクション - MF_UVtoCM
与えられたNormalとAbsoluteNormalPositionからUVを計算する関数です。
後から気づきましたが無駄に三平方の定理を使わずに原点と交点の距離からUを出す方が良いですね。
マテリアル
上記で作成した関数を利用したマテリアル。
NormalテクスチャについてはPixelNormalWSの値を用いるとエラーになります。
PixelNormalWSはNormalテクスチャで指定した値が加味された値なので定義がループして使えないということでしょうか。
Normalテクスチャの影響がないVertexNormalWSを使うとうまくいくようです。
マテリアルを用いた表示結果
面が斜めでも表示されます。
作ってみた所感
マテリアルファンクションをちゃんと使うとデバッグもしやすいし見やすくなるのでいいですね。