<?xml version="1.0" encoding="utf-8"?>

<CustomShader version="5">
    <Parameters>
        <Parameter name = "mirrorScaleAndOffsetUV"  target = "mirrorScaleAndOffsetUV"   type = "float4" group="base" defaultValue = "1 1 0 0.5"/>
        <Parameter name = "atlasInvSizeAndOffsetUV" target = "atlasInvSizeAndOffsetUV"  type = "float4" group="base" defaultValue = "0.5 0.5 0 0"/>
        <Parameter name = "RDT"                     target = "RDT"                      type = "float4" group="dirt" defaultValue = "1.0 1.0 20.0 20.0" minValue = "0.0 0.0 0.0 0.0" maxValue = "1.0 1.0 50.0 50.0"/>
        <Parameter name = "dirtColor"               target = "dirtColor"                type = "float4" group="dirt" defaultValue = "0.20 0.14 0.08 0.0"  minValue = "0.0 0.0 0.0 0.0" maxValue = "1.0 1.0 1.0 1.0"/>
        <Parameter name = "sssColor"                target = "sssColor"                 type = "float4" group="sss"  defaultValue = "0.938 0.567 0.567 1.0" minValue = "0.0 0.0 0.0 0.0" maxValue = "1.0 1.0 1.0 1.0"/>
    </Parameters>
    <UvUsages>
        <UvUsage textureName="baseMap"   uvType="uv0" uvScale="0.5"/>
        <UvUsage textureName="normalMap" uvType="uv0" uvScale="1.0"/>
        <UvUsage textureName="glossMap"  uvType="uv0" uvScale="1.0"/>
        <UvUsage textureName="dirtNmap"  uvType="uv0" uvScale="1.0"/>
        <UvUsage textureName="alphaMap"  uvType="uv0" uvScale="1.0"/>
    </UvUsages>
    <Textures>
        <Texture name = "dirtNmap" group="dirt"     defaultColorProfile = "linearRGB" defaultFilename = "../shared/characterDirt_normal.png"/>
        <Texture name = "alphaMap" group="alphaMap" defaultColorProfile = "linearRGB"/>
    </Textures>
    <VertexAttributes>
        <VertexAttribute name="uv1" group="uv1"/>
    </VertexAttributes>
    <Variations>
        <Variation name = "dirtEnabled" groups="base dirt">
<![CDATA[
    /*
    glossMap.r - smoothness (1-roughness)
    glossMap.g - ambient occlusion
    glossMap.b - dirt mask
    */
    #define DIRT_ENABLED 
]]>
        </Variation>
        <Variation name = "sssSpecular" groups="base sss">
<![CDATA[
    /*
    glossMap.r - smoothness (1-roughness)
    glossMap.g - ambient occlusion
    glossMap.b - metallic
    glossMap.a - subsurface scattering intensity
    */
#if GPU_PROFILE >= GPU_PROFILE_HIGH
    #define SUBSURFACE_SCATTERING
#endif
]]>
        </Variation>
        <Variation name = "sssSpecularDirt" groups="base dirt sss">
<![CDATA[
    /*
    glossMap.r - smoothness (1-roughness)
    glossMap.g - ambient occlusion
    glossMap.b - dirt mask
    glossMap.a - subsurface scattering intensity
    */
#if GPU_PROFILE >= GPU_PROFILE_HIGH
    #define SUBSURFACE_SCATTERING
#endif
    #define DIRT_ENABLED
]]>
        </Variation>
        <Variation name = "sssSpecularDirt_alphaMap" groups="base dirt sss alphaMap">
<![CDATA[
    /*
    alphaMap.r - alpha loaded from separate texture
    */
#if GPU_PROFILE >= GPU_PROFILE_HIGH
    #define SUBSURFACE_SCATTERING
#endif
    #define DIRT_ENABLED
    #define ALPHA_MAP
]]>
        </Variation>
        <Variation name = "sssSpecularDirt_alphaMapSecondUV" groups="base dirt sss alphaMap uv1">
<![CDATA[
    /*
    alphaMap.r - loaded from secondUV
    */
#if GPU_PROFILE >= GPU_PROFILE_HIGH
    #define SUBSURFACE_SCATTERING
#endif
    #define DIRT_ENABLED
    #define ALPHA_MAP_SECONDUV
]]>
        </Variation>
        <Variation name = "sssSpecularDirt_dirtSecondUV" groups="base dirt sss uv1">
<![CDATA[
    /*
    glossMap.b - dirt mask (loaded from secondUV set) in sssSpecularDirt
    */
#if GPU_PROFILE >= GPU_PROFILE_HIGH
    #define SUBSURFACE_SCATTERING
#endif
    #define DIRT_ENABLED
    #define DIRT_SECONDUV
]]>
        </Variation>
    </Variations>
    <LodLevel startDistance="0">
        <CodeInjections>
            <CodeInjection position="VS_OUTPUT">
<![CDATA[
    float2 normalTexCoords : TEXCOORDn;
    float2 glossmapTexCoords : TEXCOORDn;
#if defined(DIRT_SECONDUV) || defined(ALPHA_MAP_SECONDUV)
    float2 customTexCoords2 : TEXCOORDn;
#endif
]]>
            </CodeInjection>
            <CodeInjection position="CONFIG_DEFINES">
<![CDATA[
#if defined(ALPHA_MAP) || defined(ALPHA_MAP_SECONDUV)
    #define ALPHA_TESTED
#endif

#if defined(NORMAL_MAP)
    // we need different normal map coordinates than albedo map coords
    #define NORMAL_MAP_TEXCOORDS In.vs.normalTexCoords
#endif
#if defined(GLOSS_MAP)
    #define GLOSS_MAP_TEXCOORDS In.vs.glossmapTexCoords
#endif
]]>
            </CodeInjection>
            <CodeInjection position="OBJECT_PARAMETERS">
<![CDATA[
float4 mirrorScaleAndOffsetUV;
float4 atlasInvSizeAndOffsetUV;
#if defined( DIRT_ENABLED )
    float4 RDT;
    float4 dirtColor;
#endif
#if defined( SUBSURFACE_SCATTERING )
    float4 sssColor;
#endif
]]>
            </CodeInjection>
            <CodeInjection position = "SAMPLERS">
<![CDATA[
#if defined( DIRT_ENABLED )
    sampler2D dirtNmap;
#endif
#if defined(ALPHA_MAP) || defined(ALPHA_MAP_SECONDUV)
    sampler2D alphaMap;
#endif
]]>
            </CodeInjection>
            <CodeInjection position = "FS_GLOBALS">
<![CDATA[
    float4 gGloss;
#if defined( DIRT_ENABLED )
    float  gDirt;
#endif
#if defined( SUBSURFACE_SCATTERING )
    float gThickness;
    float gAlpha;
#endif
]]>
            </CodeInjection>
            <CodeInjection position="POST_SET_TEXCOORDS_VS">
<![CDATA[
#if defined(DIRT_SECONDUV) || defined(ALPHA_MAP_SECONDUV)
    // Pass second UVSet to the Pixel Shader
    Out.customTexCoords2 = convertDefaultTexCoords(In, object, In.texCoords1.xy);
#endif
    float2 newUV = getDefaultTexCoords(In, object);
    Out.normalTexCoords     = newUV;
    Out.glossmapTexCoords   = newUV;
    // mirror
    newUV = ((newUV-object.mirrorScaleAndOffsetUV.zw)*object.mirrorScaleAndOffsetUV.xy)+object.mirrorScaleAndOffsetUV.zw;
    // atlas
    newUV = newUV*object.atlasInvSizeAndOffsetUV.xy + object.atlasInvSizeAndOffsetUV.zw;
    Out.defaultTexCoords = newUV.xy;
]]>
            </CodeInjection>
            <CodeInjection position = "START_FS">
<![CDATA[
globals.gGloss = float4(0.0,1.0,0.0,0.0);
#if defined( GLOSS_MAP )
    globals.gGloss = tex2D( glossMap, In.vs.glossmapTexCoords).rgba;
#endif
#if defined( DIRT_ENABLED )
    #if defined( GLOSS_MAP )
        float texDirt  = 1 - globals.gGloss.b;
        #if defined(DIRT_SECONDUV)
            texDirt = 1 - tex2D( glossMap, In.vs.customTexCoords2).b;
        #endif
        globals.gDirt  = saturate( (texDirt*1.05 - (object.RDT.g - 0.5)) * 2 );
    #else
        globals.gDirt = 1;
    #endif
#endif
#if defined( SUBSURFACE_SCATTERING )
    globals.gAlpha = 1.0;
    #if defined( GLOSS_MAP )
        globals.gThickness = globals.gGloss.a;
    #else
        globals.gThickness = 0.0;
    #endif
#endif
]]>
            </CodeInjection>
            <CodeInjection position = "GET_UNNORMALIZED_TANGENT_SPACE_NORMAL_FS">
<![CDATA[
#if defined( DIRT_ENABLED )
    #if defined( NORMAL_MAP )
        float3 mNormal;
        #ifdef NORMAL_MAP_SIGNED_2CHANNEL
            // use BC5 signed format for the normal map
            mNormal.xy = tex2D(normalMap, NORMAL_MAP_TEXCOORDS).xy;
            mNormal.z = sqrt(1.0 - dot(mNormal.xy, mNormal.xy));
        #else
            mNormal = tex2D(normalMap, NORMAL_MAP_TEXCOORDS).xyz - 0.5;
        #endif
        float3 mDirtNmap = tex2D( dirtNmap, float2( object.RDT.z, object.RDT.w ) * NORMAL_MAP_TEXCOORDS ).xyz - 0.5;
        return mNormal + float3(mDirtNmap.xy, 0.0) * (1 - globals.gDirt);
    #endif
#endif
]]>
            </CodeInjection>
            <CodeInjection position = "GET_TANGENT_SPACE_NORMAL_FS">
<![CDATA[
#if defined( DIRT_ENABLED )
    #if defined( NORMAL_MAP )
        return normalize(getUnnormalizedTangentSpaceNormal(In, globals, object));
    #endif
#endif
]]>
            </CodeInjection>
            <CodeInjection position = "POST_DIFFUSE_COLOR_FS">
<![CDATA[
#if defined( DIRT_ENABLED )
    #if defined( SPECULAR ) && defined( GLOSS_MAP )
        diffuseColor = lerp( object.dirtColor.rgb, diffuseColor, globals.gDirt); // DirtColor lerp
    #endif
#endif
]]>
            </CodeInjection>
            <CodeInjection position="POST_GET_LIGHTING_FS">
 <![CDATA[
 #if defined( SUBSURFACE_SCATTERING )
    float fLTAmbient =      0.15;
    float fLTPower =        2.0;
    float fLTDistortion =   1.0;
    float fLTScale =        2.0;

    float fLightAttenuation = saturate(dot(normal, lightDir)) + saturate(dot(viewDir, -lightDir));

    float3 vLTLight = lightDir + normal * fLTDistortion;
    float fLTDot = pow(saturate(dot(viewDir, -vLTLight)), fLTPower) * fLTScale;
    float fLT = fLightAttenuation * (fLTDot + fLTAmbient) * globals.gThickness;
    float3 cLT = diffuseColor * lightColor * fLT * object.sssColor.rgb;
    #if defined(ALPHA_BLENDED)
        cLT *= globals.gAlpha;
    #endif
    #if defined( DIRT_ENABLED )
        cLT *= clamp(globals.gDirt,0.4,1.0);
    #endif
    lighting.xyz += cLT * lightAtten;
    #if defined( DEBUG_SHOW_PARALLAX )
        lighting.xyz = cLT * lightAtten;
    #endif  
#endif
]]>
            </CodeInjection>
            <CodeInjection position="ALPHA_FS">
<![CDATA[
#if defined(ALPHA_TESTED) || defined(ALPHA_BLENDED)
    #if defined(ALBEDO_MAP)
        #if defined(ALPHA_MAP)
            alpha = tex2D(alphaMap, In.vs.glossmapTexCoords).r;
        #elif defined(ALPHA_MAP_SECONDUV)
            alpha = tex2D(alphaMap, In.vs.customTexCoords2).r;
        #else
            // Default Behaviour 
            alpha = tex2D( baseMap, In.vs.glossmapTexCoords).a;
        #endif
    #endif
#endif
#if defined(ALPHA_BLENDED)
    reflectingLightingScale = alpha;
    #if defined( SUBSURFACE_SCATTERING )
        globals.gAlpha = alpha;
    #endif
#endif
]]>
            </CodeInjection>
            <CodeInjection position = "POST_GLOSS_COLOR_FS">
<![CDATA[
#if defined( DIRT_ENABLED )
    #if defined( SPECULAR ) && defined( GLOSS_MAP )
        float dirtRoughness = 0.8;
        roughness = lerp(dirtRoughness, 1-globals.gGloss.r, globals.gDirt);
        metalness = 0; // No metalness, since the blue channel stores the dirt mask
        bakedAO = globals.gGloss.g;
    #endif
#endif
]]>
            </CodeInjection>
            <CodeInjection position="FINAL_POS_FS">
<![CDATA[
#if defined( DEBUG_SHOW_PARALLAX )
    oColor.xyz *= 0.0001;
    oColor.xyz += lighting;
#endif    
]]>
            </CodeInjection>
        </CodeInjections>
    </LodLevel>
</CustomShader>
