Making Tera

たまに書く不定期ブログ

Unityのテクスチャマッピング

以前、Unityでテクスチャの貼り付けについて聞かれたので簡単な記事にしてみます。
先に書いておきます。分かりにくくてすみません!!


まずテクスチャマッピングについてです。
頂点(面や線)に色をぬる時、テクスチャ画像のどの部分から色を取ったらいいか?という話になります。
これを決めるのがマッピングであり、XY座標(UV座標ともいう)を指定することになります。
実際にシェーダー内では頂点ごとに以下のtex2D関数を呼び出してXY座標から色を取得しています。

tex2D(texture, xy)
texture: 色を取得したいテクスチャを選択します
xy:ここで指定したX座標とY座標にある色を取り出します

【まずは標準的なUVマッピング!】

俗にいうUVマッピングとは上記のxyにUV座標を渡す方法です。
UV座標とはデザイナーが頂点ごとに座標を設定するもので、大抵のモデルデータには付属しています。魚の開きみたいなあれです。
UVマッピングはモデルの大きさによってテクスチャも拡大されます。

【モデルのサイズに関わらずテクスチャを表示したい!】

モデルサイズに依存したくない場合はtex2D関数のxyの場所にワールド座標を渡します。*1
ワールド座標の取得方法はUnityのシェーダー機能を利用しているかどうかで変わってきます。

サーフェイスシェーダーの場合

  • worldPosを使って取得できます。
  • 例:IN.worldPos.x

頂点/フラグメントシェーダーの場合

  • 頂点にワールドマトリックスを適用することで取得できます。
  • 例:mul(_Object2World, IN.vertex)

ワールドマトリックスのような行列はあらかじめ用意されておりシェーダー内から参照できるようです。*2

_Object2Worldモデル行列
UNITY_MATRIX_MVPモデルビュー行列×射影行列 (world*view*projection)
UNITY_MATRIX_MV モデルビュー行列
UNITY_MATRIX_Vビュー行列
UNITY_MATRIX_Pプロジェクション行列
UNITY_MATRIX_VPビュー行列×射影行列
_World2Objectモデル行列の逆行列

【UIのようにテクスチャを画面に連動させたい!】

スクリーン座標にテクスチャを固定したい場合は少し複雑です。

結果を先に書くと頂点シェーダーから
ComputeScreenPos(mul(UNITY_MATRIX_MVP, v.vertex))
の値をピクセルシェーダー(フラグメントシェーダー)に渡します。
渡されたxとyをwで割った値をテクスチャ座標として使います。

除算の理由はの描画に関する行列の知識が無いと少し混乱するかもしれません。
ComputeScreenPos関数を検索すると「ウィンドウ座標を求める関数」と書かれていることが多かったのですが
実際には座標の範囲を[-w、w]から[0、w]に変換しているだけの関数となります。
画面上の座標を求めているのはmul(UNITY_MATRIX_MVP, v.vertex)の部分です。
wで割るのは通常はGPUが行っている処理を手動で行っていることになります。*3


他にもいろいろなマッピングがありますが、基本的な方法は上記の三種類だと思います。
参考に慣れば幸いであります!

*1:XYZ(float3)をどうやってfloat2にするかでマッピングの方法が変化します。

*2:DirectXで言うところのワールドマトリックスはUnityではモデル行列と呼ぶようです。

*3:GPUの透視変換はX[-w~w]Y[-w~w]Z[0~far]をwで除算しX[-1~1]Y[-1~1]Z[0~1]に変換します。