#ifndef SLOAD_H
#define SLOAD_H
#include "common.hlsli"

static const float fParallaxStartFade = 8.0f;
static const float fParallaxStopFade = 12.0f;

struct XrayMaterial
{
    float Metalness;
    float Roughness;

    float3 Normal;
    float3 Point;

    float4 Color;
    float Hemi;
    float Sun;

    float SSS;
    float AO;
};

#ifdef USE_STEEPPARALLAX
    #if defined(ALLOW_STEEPPARALLAX)

void UpdateTC(inout p_bumped_new I)
{
    if (I.position.z < fParallaxStopFade)
    {
        const float maxSamples = 25;
        const float minSamples = 5;
        const float fParallaxOffset = -0.013f;

        float3x3 TBN = float3x3(I.M1, I.M2, I.M3);
        float3 viewDir = mul(transpose(TBN), -I.position);
        viewDir = normalize(viewDir);

        // Calculate number of steps
        float nNumSteps = lerp(maxSamples, minSamples, viewDir.z);

        float fStepSize = 1.0f / nNumSteps;
        float2 vDelta = viewDir.xy * fParallaxOffset * 1.2f;
        float2 vTexOffsetPerStep = fStepSize * vDelta;

        // Prepare start data for cycle
        float2 vTexCurrentOffset = I.tcdh.xy;
        float fCurrHeight = 0.0f;
        float fCurrentBound = 1.0f;

        for (int i = 0; i < nNumSteps; ++i)
        {
            if (fCurrHeight < fCurrentBound)
            {
                vTexCurrentOffset += vTexOffsetPerStep;
                fCurrHeight = tex2Dlod(s_bumpX, float4(vTexCurrentOffset.xy, 0.0f, 0.0f)).w;

                fCurrentBound -= fStepSize;
            }
        }

        // Reconstruct previouse step's data
        vTexCurrentOffset -= vTexOffsetPerStep;
        float fPrevHeight = tex2D(s_bumpX, vTexCurrentOffset.xy).w;

        // Smooth tc position between current and previouse step
        float fDelta2 = ((fCurrentBound + fStepSize) - fPrevHeight);
        float fDelta1 = (fCurrentBound - fCurrHeight);

        float fParallaxAmount = (fCurrentBound * fDelta2 - (fCurrentBound + fStepSize) * fDelta1) / (fDelta2 - fDelta1);
        float fParallaxFade = smoothstep(fParallaxStopFade, fParallaxStartFade, I.position.z);

        float2 vParallaxOffset = vDelta * fParallaxFade * (1.0f - fParallaxAmount);
        float2 vTexCoord = I.tcdh.xy + vParallaxOffset;

        // Output the result
        I.tcdh.xy = vTexCoord;
    }
}

    #else

void UpdateTC(inout p_bumped_new I)
{
    float3x3 TBN = float3x3(I.M1, I.M2, I.M3);
    float3 viewDir = mul(transpose(TBN), -I.position);
    viewDir = normalize(viewDir);

    float height = tex2D(s_bumpX, I.tcdh.xy).w;
    height = height * parallax.x + parallax.y;

    // Output the result
    I.tcdh.xy += height * viewDir.xy;
}

    #endif
#endif

void SloadNew(inout p_bumped_new I, inout XrayMaterial M)
{
    // Enable parallax only on near objects
#if defined(USE_STEEPPARALLAX) && defined(USE_HIGH_QUALITY)
    UpdateTC(I);
#endif

    M.Color = tex2D(s_base, I.tcdh.xy);

#ifdef USE_BUMP
    float4 Bump = tex2D(s_bump, I.tcdh.xy);
    float4 BumpX = tex2D(s_bumpX, I.tcdh.xy);

    //	#ifndef USE_PBR
    M.Normal = Bump.wzy + BumpX.xyz - 1.0f;
    M.Normal.z *= 0.5f;

    M.Roughness = Bump.x * Bump.x;
    M.Metalness = 0.0f;

    M.SSS = 0.0;
    M.AO = 1.0;
//	#endif
#else
    M.Normal = float3(0.0f, 0.0f, 1.0f);

    M.Roughness = def_gloss;
    M.Metalness = 0.0f;

    M.SSS = 0.0f;
    M.AO = 1.0f;
#endif

#ifdef USE_TDETAIL
    float2 tcdbump = I.tcdh.xy * dt_params.xy;
    float4 Detail = tex2D(s_detail, tcdbump);
    #ifndef USE_PBR
    M.Color.xyz *= Detail.xyz * 2.0f;

        #ifdef USE_TDETAIL_BUMP
    float4 DetailBump = tex2D(s_detailBump, tcdbump);
    float4 DetailBumpX = tex2D(s_detailBumpX, tcdbump);
    M.Normal += DetailBump.wzy + DetailBumpX.xyz - 1.0f;
    M.Roughness *= DetailBump.x * 2.0f;
        #else
    M.Roughness *= Detail.w * 2.0f;
        #endif
    #endif
#endif

#ifndef USE_PBR
    M.Metalness = M.Roughness * 0.1f;
    M.Roughness = saturate(1.0f - M.Roughness);
#endif
}

#endif
