前回の続きです。
今回は頂点シェーダー部分とフラグメントシェーダー(ピクセルシェーダー)部分を3dsMaxへ移植するメモです。
頂点シェーダーでの処理の比較
頂点座標(プロジェクション空間)
Unity
UnityObjectToClipPos(v.vertex)
mul(UNITY_MATRIX_MVP, float4(v.vertex, 1.0))
上記二つは同じ意味で、頂点座標をカメラクリップ座標系(モデル座標系→ビュー座標系→プロジェクション座標系)へ変換します。これは以下で実装できます。
HLSL
float4x4 mvpMatrix : WorldViewProj; // Model*View*Projection 一番上で宣言
o.pos = mul(v.vertex, mvpMatrix);
頂点座標(ワールド空間)
Unity
o.posWorld = mul(unity_ObjectToWorld, v.vertex);
これは、頂点座標をワールド座標系に変換する処理です。以下で対応できます。
HLSL
float4x4 mMatrix : World;// モデル(ワールド)マトリクス 一番上で宣言
WorldPosition = mul(pos, mMatrix);
法線情報(ワールド空間)
Unity
o.Normal = UnityObjectToWorldNormal(v.normal);
これは、ローカル空間系にある法線情報をワールド座標系に変換することを意味しますので以下で対応できます。
HLSL
float4x4 mMatrix : World; // モデル(ワールド)マトリクス 一番上で宣言
o.Normal = normalize(mul(IN.Normal.xyz, (float3x3)mMatrix ));
Unityではモデル座標系をワールド座標系と言うみたいですね。
フラグメント(ピクセル)シェーダーでの処理の比較
カメラの向いている方向を求める
Unity
float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
これは以下のように書き換えました。
HLSL
float4x4 viewInverseMatrix : ViewInverse < string UIWidget = "None"; >;//一番上で宣言
CameraPosition = viewInverseMatrix[3].xyz; float3 viewDirection = normalize(CameraPosition - i.WorldPosition.xyz);
これでいけるはずです。
テクスチャを読み込む
Unity
float2 Set_UV0 = i.uv0;
float4 _BaseMap_var = tex2D(_BaseMap,TRANSFORM_TEX(Set_UV0, _BaseMap));
HLSL
//フラグメント外で宣言しておく
//MipMapとかWrap Modeの設定(SamplerState)です。UnityではGUIで設定します。
SamplerState g_TopSampler{
Filter = MIN_MAG_MIP_POINT;
AddressU = WRAP;
AddressV = WRAP;
AddressW = WRAP;
};
//あらかじめGUIから取得したテクスチャマップ(_BaseMap)とSamplerState、UVを指定してテクスチャを開きます。
float4 Basemap = _BaseMap.Sample(g_TopSampler, i.UV0.xy);
ノーマルマップを読み込む
unity
float3 _NormalMap_var = UnpackNormal(tex2D(_NormalMap,TRANSFORM_TEX(Set_UV0, _NormalMap)));
HLSL
//テクスチャは通常0~1なので、2倍にしてから-1して-1~1に範囲を広げる関数を用意します。
float3 ExpandRangeFunction(float3 Vector){
float3 NormalMap = (Vector * 2.0);
float3 NormalMapwide = (NormalMap - 1.0);
return NormalMapwide;
}
//ノーマルマップを取得
float4 Sampler = _NormalMap.Sample(g_TopSampler, i.UV0.xy);
//範囲を広げます。
float3 NormalMapH = ExpandRangeFunction(Sampler.xyz);
//「ワールド空間」のNormal,Bitangent(BiNormal),Tangentから、行列を生成。
float3x3 tangentTransform = float3x3(i.Tangent, i.Binormal, i.Normal);
//ノーマルマップをUV空間からワールド空間へ変換。
float3 normalDirection = normalize(mul(NormalMapH, tangentTransform));
これで、必要な要素は揃ったので、3dsMaxへの移植はできると思います。