SuiTechLog

Unity,Arduino,RaspberryPiなど、モノづくり系を気ままに書き残すブログ。

Unityのシェーダーを3dsMaxのビューポートシェーダーへ移植する その3 頂点シェーダー・フラグメントシェーダー


前回の続きです。

今回は頂点シェーダー部分とフラグメントシェーダー(ピクセルシェーダー)部分を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への移植はできると思います。

 

続き 設定編