// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
namespace Stride.Rendering.Materials
{
    /// <summary>
    /// Performs a Cel shading
    /// </summary>
    class MaterialSurfaceShadingDiffuseCelShading<bool TIsEnergyConservative, float FakeNDotL> : IMaterialSurfaceShading, Math, MaterialPixelShadingStream, LightStream, ShadowGroup
    {
        compose IMaterialCelShadingLightFunction celLightFunction;

        override float3 ComputeDirectLightContribution()
        {
            float3 celLight = streams.NdotL * streams.lightAttenuation;
            
            if (FakeNDotL > 0)
            {
				celLight = celLightFunction.Compute(celLight * FakeNDotL);
            }
            else
            {
				celLight = celLightFunction.Compute(celLight);
            }
            
			float3 lighting = celLight * streams.lightColor * streams.shadowColor * streams.lightDirectAmbientOcclusion;      

            var diffuseColor = streams.matDiffuseVisible;
            if (TIsEnergyConservative)
            {
                // Approximation see: http://research.tri-ace.com/Data/course_note_practical_implementation_at_triace.pdf
                diffuseColor *= (1 - streams.matSpecularVisible);
            }

            float3 result =  diffuseColor / PI * lighting * streams.matDiffuseSpecularAlphaBlend.x;
            return result;
        }

        override float3 ComputeEnvironmentLightContribution()
        {
            // TODO: Check how to factorize this with DirectLight
            var diffuseColor = streams.matDiffuseVisible;
            if (TIsEnergyConservative)
            {
                diffuseColor *= (1 - streams.matSpecularVisible);
            }

            float3 celLight = celLightFunction.Compute(streams.envLightDiffuseColor);
            return diffuseColor * celLight;
        }
    };
}
