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

<CustomShader version="5">
    <Textures>
        <Texture name = "mMaskMap"       defaultColorProfile = "linearRGB"   group="base"  defaultFilename = "../../shared/default_specular.png"/>
        <Texture name = "mDirtDiffuse"   defaultColorProfile = "sRGB"        group="base"  defaultFilename = "../../shared/mapDirt_diffuse.png"/>
        <Texture name = "mDirtNormal"    defaultColorProfile = "linearRGB"   group="base"  defaultFilename = "../../shared/mapDirt_normal.png"/>
        <Texture name = "mMossDiffuse"   defaultColorProfile = "sRGB"        group="base"  defaultFilename = "../../shared/mapMoss_diffuse.png"/>
        <Texture name = "mMossNormal"    defaultColorProfile = "linearRGB"   group="base"  defaultFilename = "../../shared/mapMoss_normal.png"/>
        <Texture name = "mGradientMap"   defaultColorProfile = "sRGB"        group="color" defaultFilename = "../../maps/textures/shared/defaultGradient_diffuse.png"/>
        <Texture name = "baseMap"   group = "array" type = "2dArray"/>
        <Texture name = "normalMap" group = "array" type = "2dArray"/>
        <Texture name = "glossMap"  group = "array" type = "2dArray"/>
    </Textures>
    <VertexAttributes>
        <VertexAttribute name="uv1" group="base"/>
    </VertexAttributes>
    <UvUsages>
        <UvUsage textureName="baseMap"       uvType="uv0" uvScale="1.0"/>
        <UvUsage textureName="normalMap"     uvType="uv0" uvScale="1.0"/>
        <UvUsage textureName="glossMap"      uvType="uv0" uvScale="1.0"/>
        <UvUsage textureName="mGradientMap"  uvType="uv0" uvScale="1.0"/>
        <UvUsage textureName="mMaskMap"      uvType="uv1" uvScale="1.0"/>
        <UvUsage textureName="mDirtDiffuse"  uvType="worldspace"/>
        <UvUsage textureName="mDirtNormal"   uvType="worldspace"/>
        <UvUsage textureName="mMossDiffuse"  uvType="worldspace"/>
        <UvUsage textureName="mMossNormal"   uvType="worldspace"/>
    </UvUsages>
    <Variations>
        <Variation name = "COLOR_MASK" groups="base color">
<![CDATA[
    // if uv.x<0 load gradientMap from baseMap
    #define COLOR_MASK
]]>
        </Variation>
        <Variation name = "USE_TEXTURE_ARRAY" groups="base array">
<![CDATA[
    // Force baseMap, normalMap, glossMap to arrays
    #define USE_TEXTURE_ARRAY
]]>
        </Variation>
        <Variation name = "USE_TEXTURE_ARRAY_COLOR_MASK" groups="base color array">
<![CDATA[
    // Force baseMap, normalMap, glossMap to arrays
    #define USE_TEXTURE_ARRAY
    #define COLOR_MASK
]]>
        </Variation>
    </Variations>
    <LodLevel startDistance="0">
        <CodeInjections>
            <CodeInjection position="SHARED_START">
<![CDATA[
#if defined( USE_TEXTURE_ARRAY )
    #undef ALBEDO_MAP
    #undef NORMAL_MAP
    #undef GLOSS_MAP
#endif
]]>
            </CodeInjection>
            <CodeInjection position="CONFIG_DEFINES">
<![CDATA[
#if defined(COOK_TORRANCE_GGX_SHADING)
    #define GEOMETRIC_SPECULAR_ANTIALISING
#endif
]]>
            </CodeInjection>
            <CodeInjection position = "SAMPLERS">
<![CDATA[
#if defined( USE_TEXTURE_ARRAY )
    sampler2DArray baseMap;
    sampler2DArray normalMap;
    sampler2DArray glossMap;
#endif
sampler2D mMaskMap;
sampler2D mDirtDiffuse;
sampler2D mDirtNormal;
sampler2D mMossDiffuse;
sampler2D mMossNormal;
#if defined( COLOR_MASK )
    sampler2D mGradientMap;
#endif
]]>
            </CodeInjection>
            <CodeInjection position = "FS_GLOBALS">
<![CDATA[
    float  gMossMask;
    float  gAO;
    float  gDirtMask;
    float4 gDirtDiffuse; // alpha channel must be exists with black-white gradients
    float4 gDirtNormal;
    float  gDirtRough;
    float4 gMossDiffuse; // alpha channel must be exists with black-white gradients
    float4 gMossNormal;
    float  gMossRough;
    float  gIndex;
]]>
            </CodeInjection>
            <CodeInjection position="VS_OUTPUT">
<![CDATA[
    float2 maskMapTexCoords : TEXCOORDn;
    float2 texCoordsX       : TEXCOORDn;
    float2 texCoordsY       : TEXCOORDn;
    float2 texCoordsZ       : TEXCOORDn;
    float3 localNormal      : TEXCOORDn;
]]>
            </CodeInjection>
            <CodeInjection position="POST_SET_TEXCOORDS_VS">
<![CDATA[
    Out.maskMapTexCoords = convertDefaultTexCoords( In, object, In.texCoords1.xy ); // Pass second UVSet to the Pixel Shader
    float3 localPosition = In.position.xyz;
    float mUVScale = 1.0;
    Out.texCoordsX = mUVScale * localPosition.yz;
    Out.texCoordsY = mUVScale * localPosition.xz;
    Out.texCoordsZ = mUVScale * localPosition.xy;
    Out.localNormal = normalize(In.normal.xyz);
]]>
            </CodeInjection>
            <CodeInjection position = "START_FS">
<![CDATA[
    globals.gMossMask = 0.0;
    globals.gAO       = 1.0;
    globals.gDirtMask = 0.0;
    globals.gDirtDiffuse = float4( 0.5,0.5,0.5,1.0 );
    globals.gDirtNormal  = float4( 0.5,0.5,1.0,1.0 );
    globals.gDirtRough   = 0.9865;
    globals.gMossDiffuse = float4( 0.5,0.5,0.5,1.0 );
    globals.gMossNormal  = float4( 0.5,0.5,1.0,1.0 );
    globals.gMossRough   = 0.9865;
    {
        float3 mAbsNormal   = abs(In.vs.localNormal);
        mAbsNormal /= (mAbsNormal.x + mAbsNormal.y + mAbsNormal.z);
        float2 uvs = mAbsNormal.x > mAbsNormal.y ? (mAbsNormal.x > mAbsNormal.z ? In.vs.texCoordsX : In.vs.texCoordsZ) : (mAbsNormal.y > mAbsNormal.z ? In.vs.texCoordsY : In.vs.texCoordsZ);
        globals.gDirtDiffuse = tex2D( mDirtDiffuse, uvs ).rgba;
        globals.gDirtNormal  = tex2D( mDirtNormal,  uvs ).rgba;
        globals.gMossDiffuse = tex2D( mMossDiffuse, uvs ).rgba;
        globals.gMossNormal  = tex2D( mMossNormal,  uvs ).rgba;
    }
    float3 mMask  = tex2D( mMaskMap, In.vs.maskMapTexCoords ).rgb;
    globals.gMossMask = mMask.r;
    globals.gAO       = mMask.g;
    globals.gDirtMask = mMask.b;
    globals.gIndex = floor(ALBEDO_MAP_TEXCOORDS.y + 8.0);
]]>
            </CodeInjection>
            <CodeInjection position = "GET_UNNORMALIZED_TANGENT_SPACE_NORMAL_FS">
<![CDATA[
#if defined( USE_TEXTURE_ARRAY )
    #define NORMAL_MAP
#endif
#if defined( NORMAL_MAP )
    float3 mNormal;
    #if defined( USE_TEXTURE_ARRAY )
        mNormal   = tex2D( normalMap, float3(NORMAL_MAP_TEXCOORDS, globals.gIndex) ).xyz - 0.5;
    #else
        mNormal   = tex2D( normalMap, NORMAL_MAP_TEXCOORDS ).xyz - 0.5;
    #endif
    float3 mMossNmap = globals.gMossNormal.xyz - 0.5;
    float3 mDirtNmap = globals.gDirtNormal.xyz - 0.5;
    mNormal.xy += mMossNmap.xy*globals.gMossMask + mDirtNmap.xy*globals.gDirtMask;
    return mNormal;
#endif
]]>
            </CodeInjection>
            <CodeInjection position = "GET_TANGENT_SPACE_NORMAL_FS">
<![CDATA[
#if defined( NORMAL_MAP )
    return normalize(getUnnormalizedTangentSpaceNormal(In, globals, object));
#endif
]]>
            </CodeInjection>
            <CodeInjection position = "POST_DIFFUSE_COLOR_FS">
<![CDATA[
#if defined( USE_TEXTURE_ARRAY )
    #define ALBEDO_MAP
#endif
#if defined(ALBEDO_MAP)
    #if defined( USE_TEXTURE_ARRAY )
        diffuseColor = tex2D(baseMap, float3(ALBEDO_MAP_TEXCOORDS, globals.gIndex)).xyz;
    #else
        diffuseColor = tex2D(baseMap, ALBEDO_MAP_TEXCOORDS).xyz;
    #endif
    #if  defined( COLOR_MASK )
        if ( ALBEDO_MAP_TEXCOORDS.x < 0.0 ){
            float y = 0.5;
            #if defined( USE_TEXTURE_ARRAY )
                y = (globals.gIndex+0.5) / 16.0;
            #endif
            float x = diffuseColor.r * 0.5 + 0.25; // Lookup from middle of left pixel to middle of right pixel
            diffuseColor = tex2D( mGradientMap, float2(x,y) ).xyz;
        }
    #endif
    diffuseColor.rgb = lerp( diffuseColor.rgb, globals.gMossDiffuse.rgb, globals.gMossMask );
    diffuseColor.rgb = lerp( diffuseColor.rgb, globals.gDirtDiffuse.rgb, globals.gDirtMask );
#endif
]]>
            </CodeInjection>
            <CodeInjection position = "POST_GLOSS_COLOR_FS">
<![CDATA[
#if defined( USE_TEXTURE_ARRAY )
    #define GLOSS_MAP
#endif
#if defined(GLOSS_MAP)
    #if defined( USE_TEXTURE_ARRAY )
        float3 pbrMapValues = tex2D(glossMap, float3(GLOSS_MAP_TEXCOORDS, globals.gIndex)).xyz;
        roughness    = 1-pbrMapValues.x;
        bakedAO      = pbrMapValues.y;
        metalness    = pbrMapValues.z;
    #endif
    roughness = lerp( roughness, globals.gMossRough, globals.gMossMask );
    roughness = lerp( roughness, globals.gDirtRough, globals.gDirtMask );
    metalness = lerp( metalness, 0.0, globals.gMossMask );
    metalness = lerp( metalness, 0.0, globals.gDirtMask );
    bakedAO  *= globals.gAO;
#endif
]]>
            </CodeInjection>
        </CodeInjections>
    </LodLevel>
</CustomShader>
