matrix World;           // ワールド変換行列
matrix View;            // ビュー変換行列
matrix Projection;      // 透視変換行列
matrix SMWorldViewProj; // ワールド×ビュー×透視変換行列(シャドウマップ用)
float4 Diffuse;         // ディフューズ色
float3 Light;           // 光源座標(ビュー座標系)


// テクスチャ
Texture2D Tex2D : register(t0);
Texture2D ShadowMap : register(t1); // シャドウマップ

// テクスチャ・サンプラ
SamplerState smpWrap   : register(s0);
SamplerState smpBorder : register(s1);

// **************************************************
// 3Dオブジェクトの描画
// **************************************************

// 頂点シェーダの入力データ定義
struct VS_INPUT {
    float3 Pos  : POSITION;  // 頂点座標(モデル座標系)
    float3 Norm : NORMAL;    // 法線ベクトル(モデル座標系)
    float2 Tex  : TEXTURE;   // テクスチャ座標
};

// ピクセル シェーダの入力データ定義
struct PS_INPUT {
    float4 Pos  : SV_POSITION; // 頂点座標(透視座標系)
    float3 PosView  : POSVIEW; // 頂点座標(ビュー座標系)
    float3 Norm : NORMAL;      // 法線ベクトル(ビュー座標系)
    float2 Tex  : TEXTURE;     // テクスチャ座標
    float3 PosSM: POSITION_SM; // 頂点座標(シャドウマップの透視座標系)
};

// 頂点シェーダの関数
PS_INPUT VS(VS_INPUT input) {
    PS_INPUT output;

    // 頂点座標　モデル座標系→透視座標系
    float4 pos4 = float4(input.Pos, 1.0);
    pos4 = mul(pos4, World);
    pos4 = mul(pos4, View);
    output.PosView = pos4.xyz / pos4.w;
    output.Pos = mul(pos4, Projection);

    // 法線ベクトル　モデル座標系→ビュー座標系
    float3 Norm = mul(input.Norm, (float3x3)World);
    output.Norm = mul(Norm, (float3x3)View);

    // テクスチャ座標
    output.Tex = input.Tex;

    // 頂点座標　モデル座標系→透視座標系(シャドウマップ)
    pos4 = mul(float4(input.Pos, 1.0), SMWorldViewProj);
    pos4.xyz = pos4.xyz / pos4.w;
    output.PosSM.x = (pos4.x + 1.0) / 2.0;
    output.PosSM.y = (-pos4.y + 1.0) / 2.0;
    output.PosSM.z = pos4.z;

    // 出力
    return output;
}

// ライティング計算
float lighting(PS_INPUT input)
{
    // 光源ベクトル
    float3 light = Light - input.PosView;
    // 距離
    float  leng = length(light);
    // 明るさ
    return 30 * dot(normalize(light), normalize(input.Norm)) / pow(leng, 2);
}

// ピクセル シェーダの関数
float4 PS(PS_INPUT input) : SV_TARGET
{
    // ライティング計算
    float bright = lighting(input);

    // テクスチャ取得
    float4 texCol = Tex2D.Sample(smpWrap, input.Tex);         // テクセル読み込み

    // シャドウマップ
    float sm = ShadowMap.Sample(smpBorder, input.PosSM.xy);
    float sma = (input.PosSM.z < sm) ? 1.0 : 0.5;

    // 色
    return saturate(bright * texCol * Diffuse * sma);
}

// **************************************************
// シャドウマップを使わない3Dオブジェクトの描画
// **************************************************

// ピクセル シェーダの関数
float4 PS_NOSM(PS_INPUT input) : SV_TARGET
{
    // ライティング計算
    float bright = lighting(input);

    // テクスチャ取得
    float4 texCol = Tex2D.Sample(smpWrap, input.Tex);         // テクセル読み込み

    // 色
    return saturate(bright * texCol * Diffuse);
}

// **************************************************
// シャドウマップの描画
// **************************************************

// 頂点シェーダの関数
float4 VS_SM(VS_INPUT input) : SV_POSITION {
    // 頂点座標　モデル座標系→透視座標系
    float4 pos4 = float4(input.Pos, 1.0);
    pos4 = mul(pos4, World);
    pos4 = mul(pos4, View);
    return mul(pos4, Projection);
}

