/*
 * Copyright (c) Contributors to the Open 3D Engine Project.
 * For complete copyright and license terms please see the LICENSE at the root of this distribution.
 *
 * SPDX-License-Identifier: Apache-2.0 OR MIT
 *
 */

#include <Atom/Features/SrgSemantics.azsli>

ShaderResourceGroup ShadowViewSrg : SRG_PerObject
{
    row_major float4x4 m_worldMatrix;
    row_major float4x4 m_viewProjectionMatrix;
    row_major float4x4 m_lightViewProjectionMatrix;
    float4 m_lightPosition;
	
    float4 m_ambientColor;
    float4 m_diffuseColor;
	
    Texture2D m_depthMapTexture;
    
    Sampler ShadowSampler
    {
       AddressU = Clamp;
       AddressV = Clamp;
    };
}    

struct VSInput
{
    float3 m_position : POSITION;
    float4 m_color : COLOR0;
    float3 m_normal: NORMAL;
};

struct VSOutput
{
    float4 m_position : SV_Position;
    float4 m_color : COLOR0;
    float3 m_normal: NORMAL;
    float4 m_lightViewPosition : TEXCOORD1;
    float3 m_worldPosition : TEXCOORD2;
};

VSOutput MainVS(VSInput vsInput)
{
    VSOutput OUT;
    
    OUT.m_worldPosition = mul(ShadowViewSrg::m_worldMatrix, float4(vsInput.m_position, 1.0)).xyz;
	
    OUT.m_position = mul(ShadowViewSrg::m_viewProjectionMatrix, float4(OUT.m_worldPosition, 1.0));
	
    OUT.m_lightViewPosition = mul(ShadowViewSrg::m_lightViewProjectionMatrix, float4(OUT.m_worldPosition, 1.0));
	
    OUT.m_color = vsInput.m_color;
	
    float4 normalsToWorld = mul(float4(vsInput.m_normal, 0.0), ShadowViewSrg::m_worldMatrix);
    OUT.m_normal = normalsToWorld.xyz;
    OUT.m_normal = normalize(OUT.m_normal);
	
    return OUT;
}

struct PSOutput
{
    float4 m_color : SV_Target0;
};


PSOutput MainPS(VSOutput vsOutput)
{
    PSOutput OUT;
    float bias;
    float shadowMask;
    float lightIntensity;
    float3 projectTexCoord;
    float3 lightDirection;
    
    
    bias = 0.001f;
    OUT.m_color = ShadowViewSrg::m_ambientColor;
    
    lightDirection = ShadowViewSrg::m_lightPosition.xyz - vsOutput.m_worldPosition;
    lightDirection = normalize(lightDirection);
      
    projectTexCoord.xyz = vsOutput.m_lightViewPosition.xyz / vsOutput.m_lightViewPosition.w;	
    projectTexCoord.xy = (projectTexCoord.xy / float2(2.0f, -2.0f)) + 0.5f;  
    projectTexCoord.z -= bias;

    shadowMask = ShadowViewSrg::m_depthMapTexture.Sample(ShadowViewSrg::ShadowSampler, projectTexCoord.xy).r;
    
    shadowMask = float(shadowMask > projectTexCoord.z);

    lightIntensity = shadowMask * saturate(dot(normalize(vsOutput.m_normal), lightDirection));

    OUT.m_color += (ShadowViewSrg::m_diffuseColor * lightIntensity);
    OUT.m_color = saturate(OUT.m_color);

    OUT.m_color = OUT.m_color * vsOutput.m_color;

    return OUT;
}
