こんにちは。ヤマヤタケシです。
前回、法線マップの理論は見えた!ということで実装を始めました。
やっぱり、理論と実践は違いますね。
というか、理論だけでは実装ができないという現実・・・。
普通に取得しても、x,y,zの色が同じになったのです。
float3 normal = tex2D (_NormalTex, i.uv); float4 col = float4(col.xyz, 1); return col;
Unityのテクスチャの設定をNormal map -> Color に戻すとちゃんと、x,y,zが別のものが入ってきました。
???
調べました。
Unity、DirectX環境でのNormalMapの内部的なフォーマットお勉強
「GLESやスマホフラグが立っていない環境ではDirectXモードということでNormalDiffuseの法線サンプリング計算はDXT5nを前提に「YW要素をXYZWのXYに変換し、Z要素をXYから復元して埋める」計算に切り替わってますね。」
な、なんだってー!
どうやら、テクスチャにはXXXYな形で入っているので、tex2Dのxyzは同じ値になるんですね。
知らんがな・・・。
ということで、UnityCG.incにUnpackNormal が定義されています。
inline fixed3 UnpackNormal(fixed4 packednormal) { #if defined(UNITY_NO_DXT5nm) return packednormal.xyz * 2 - 1; #else return UnpackNormalDXT5nm(packednormal); #endif }
結論!
こんな感じで解決です。
float3 normal = UnpackNormal (tex2D (_NormalTex, i.uv)); float4 col = float4(col.xyz, 1); return col;
それにしても、float3, half3, fixed3 のどれを使えば良いのやら・・・。
ありました。
シェーダーを書く場合のパフォーマンスのヒント
引用します。
ワールド空間の位置とテクスチャ座標には、float 型を使用してください。
上記以外 (ベクトル、HDR カラーなど) には、half で始めます。必要なときだけ、増加します。
テクスチャデータのとても簡易な操作には、fixed を使用します。
なるほど!
と、思った次の行には・・・。
あらゆる現代のデスクトップ GPU は、常にすべての事を完全な 浮動小数点数精度で計算していて、そのため、根底では float/half/fixed の結果はまったく同じになります。
なんてこった。
じゃあ、floatを使うさ!
ただ、モバイルでは影響があるらしいです。
そんじゃまた。