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

<CustomShader version="5">
    <Parameters>
        <Parameter name="fillTypeId"       target="fillTypeId"        type="float"  group="base" defaultValue="0"/>
        <Parameter name="fadeProgress"     target="fadeProgress"      type="float4" group="base" defaultValue = "1.0 1.0 0.0 0.0" minValue = "-1.0 -1.0 0.0 0.0" maxValue = "1.0 1.0 1.0 1.0"/>
        <Parameter name="fadeScale"        target="fadeScale"         type="float"  group="base" defaultValue = "-0.025" minValue = "-1.0" maxValue = "1.0"/>
        <Parameter name="uvSpeedMult"      target="uvSpeedMult"       type="float"  group="base" defaultValue = "1.0" minValue = "-2.0" maxValue = "2.0"/>
        <Parameter name="shapeScaleSpread" target="shapeScaleSpread"  type="float4" group="pipe" defaultValue = "1 1 0.0 0.0"/>
        <Parameter name="controlPoint"     target="controlPoint"      type="float4" group="pipe" defaultValue = "10.0 0.0 1.0 0.0"/>
    </Parameters>
    <UvUsages/>
    <Textures>
        <Texture name="baseMap"   group="base" type="2dArray"/>
        <Texture name="glossMap"  group="base" type="2dArray"/>
        <Texture name="normalMap" group="base" type="2dArray"/>
        <Texture name="fadeMask"  group="base" defaultColorProfile = "linearRGB" defaultFilename = "$data/effects/unload/fadeMask_diffuse.png" defaultWrap="false"/>
        <Texture name="cloudMask" group="base" defaultColorProfile = "linearRGB" defaultFilename = "$data/effects/unload/clouds_diffuse.png"/>
    </Textures>
    <Variations>
        <Variation name = "pipeEffect" groups="base pipe">
<![CDATA[
    #define PIPE_EFFECT
]]>
        </Variation>
    </Variations>
    <VertexAttributes>
        <VertexAttribute name="uv1"   group="base"/>
        <VertexAttribute name="color" group="base"/>
    </VertexAttributes>
    <LodLevel startDistance="0">
        <CodeInjections>
            <CodeInjection position="SHARED_START">
<![CDATA[
#define ALPHA_TESTED
//#define STATIC_TEST_GEOMETRY
#if !defined(STATIC_TEST_GEOMETRY)
    #define ALBEDO_MAP_TYPE sampler2DArray
    #define NORMAL_MAP_TYPE sampler2DArray
    #define GLOSS_MAP_TYPE  sampler2DArray
#endif
]]>
            </CodeInjection>
            <CodeInjection position="SAMPLERS">
<![CDATA[
    sampler2D fadeMask;
    sampler2D cloudMask;
]]>
            </CodeInjection>
            <CodeInjection position="OBJECT_PARAMETERS">
<![CDATA[
    /*
    fadeProgress.x - FadeIN:    start = -1.0 end = 1.0
    fadeProgress.y - FadeOUT:   start = 1.0 end = -1.0

    Fully Visible       fadeProgress.x = 1.0        "1.0 1.0 0.0 0.0"
                        fadeProgress.y = 1.0
    Fully Invisible     fadeProgress.x = -1.0       "-1.0 -1.0 0.0 0.0"
                        fadeProgress.y = -1.0
    */
    float4 fadeProgress;
    float fadeScale;   // scale ( by normals ) vertices of the geo while fading
    float uvSpeedMult; // multiplication to defined in the shader uvSpeed
    float fillTypeId;  // index from fillType Array
#if defined( PIPE_EFFECT )
/*
    shapeScaleSpread.x - shape width scaler
    shapeScaleSpread.y - shape hight scaler
    shapeScaleSpread.z - spread at the end
*/
    float4 shapeScaleSpread;
/*
    controlPoint.x - distance to the point
    controlPoint.y - bending in radians
*/
    float4 controlPoint;
#endif
]]>
            </CodeInjection>
            <CodeInjection position="LIB_FUNCTION_VS">
<![CDATA[
// Custom vertex functions
float3 getCustomPositionVS( VS_INPUT    In,
                      ObjectParameters& object,
                                float   mSpeed ){
    // =================================
    float3 mDeformed = In.position.xyz;
#if defined( PIPE_EFFECT )
    float  mGrad             = convertDefaultTexCoords( In, object, In.texCoords0.xy ).x;
    float  mGradSide         = In.color.g;
    float3 mDeformedPosition = In.position.xyz;
    mDeformedPosition.z     /= 10;
    // =================================
    // FADEIN FADEOUT DEFORM
    float mFadeIn  = 0.5 * ( object.fadeProgress.x ) + 0.5;
    float mFadeOut = 0.5 * ( object.fadeProgress.y ) + 0.5;
    mDeformedPosition = lerp( object.fadeScale * In.normal.xyz, mDeformedPosition, mFadeIn  );
    // =================================
    // INIT DEFORM
    float mSpread         = object.shapeScaleSpread.z;
    mSpread               = max( 1.0, 1 + mSpread );
    mDeformedPosition.xy  = lerp( mDeformedPosition.xy, mDeformedPosition.xy * mSpread, mGrad );
    float2 mShapeScale    = max( object.shapeScaleSpread.xy, 0.001 );
    mDeformedPosition.xy *= mShapeScale.xy;
    // =================================
    // OVER SIZE
    float mControlPoint = max( object.controlPoint.x, 0.001);
    mControlPoint = mControlPoint - min(sign(mDeformedPosition.z), 0) * (10 - mControlPoint); // unchanged z position of z negative vertices
    mDeformedPosition.z *= mControlPoint;
    // =================================
    // ANIMATION
    float mFrequency    = mSpeed - mDeformedPosition.z * 3.0;
    float mAmplitude    = 0.1 * mGrad * mGradSide;
    float mOffset       = ( 0.5 * sin( mFrequency ) + 0.5 ) * mAmplitude;
    mDeformedPosition  += mOffset * In.normal.xyz;
    // =================================
    // BENDING
    float mAngle  = object.controlPoint.y;
    float3 newPos = mDeformedPosition;
    mGrad = clamp( sin( 1.5 * mGrad),0,1);
    float mCos    = cos(mAngle);
    float mSin    = sin(mAngle);
    float3 v1     = float3(0.0, 0.0, 0.0);
    float3 v2     = float3(0.0, 0.0, 0.0);
    v1.y = mCos; v1.z = -mSin;
    v2.y = mSin; v2.z = mCos;
    newPos.y = dot( mDeformedPosition, v1 );
    newPos.z = dot( mDeformedPosition, v2 );
    mDeformed = lerp( mDeformedPosition, newPos, mGrad );
#else
    float mAmplitude = 0.25 * In.color.g * In.color.r;
    float3 mFreq = 1.5*In.position.xyz;
    float3 mOffset = ( 0.25 * sin( mSpeed - In.color.r * mFreq.x+mFreq.y+mFreq.z ) + 0.5 ) * mAmplitude;
    float3 mDeformedPosition = mOffset * In.normal.xyz;
    // =================================
    // FADEIN
    mDeformedPosition = lerp( object.fadeScale * In.normal.xyz, mDeformedPosition, 0.5 * ( object.fadeProgress.x ) + 0.5 );
    // FADEOUT
    mDeformedPosition = lerp( object.fadeScale * In.normal.xyz, mDeformedPosition, 0.5 * ( object.fadeProgress.y ) + 0.5 );
    // =================================
    mDeformed = In.position.xyz + mDeformedPosition;
#endif
    return mDeformed.xyz;
}
]]>
            </CodeInjection>
            <CodeInjection position="VS_OUTPUT">
<![CDATA[
float2 defaultTexCoords2 : TEXCOORDn;
]]>
            </CodeInjection>
            <CodeInjection position="POST_SET_TEXCOORDS_VS">
<![CDATA[
    Out.defaultTexCoords  = convertDefaultTexCoords( In, object, In.texCoords0.xy );
    Out.defaultTexCoords2 = convertDefaultTexCoords( In, object, In.texCoords1.xy );
#if defined( PIPE_EFFECT )
    float uvProportionScaleFactor = 1.0;
    float mSpread            = object.shapeScaleSpread.z;
    mSpread                  = max( 1.0, 1 + mSpread );
    float mGrad              = Out.defaultTexCoords.x;
    uvProportionScaleFactor  = max( object.controlPoint.x, 0.001);
    Out.defaultTexCoords.x  *= uvProportionScaleFactor;
    Out.defaultTexCoords2.x *= uvProportionScaleFactor;
    uvProportionScaleFactor  = lerp( 1, mSpread, mGrad );
    Out.defaultTexCoords.y  *= uvProportionScaleFactor;
    Out.defaultTexCoords2.y *= uvProportionScaleFactor;
#endif
]]>
            </CodeInjection>
            <CodeInjection position="GET_POSITION_VS">
<![CDATA[
#if defined( PIPE_EFFECT )
    float mSpeed = 36.0 * cTime_s;
#else
    float mSpeed = 10.0 * cTime_s;
#endif
    float3 mDeformed = getCustomPositionVS(In, object, mSpeed);
#if defined(SKINNING)
    return skinPoint(mDeformed.xyz, In, object) - float3(invViewMatrix[0][3], invViewMatrix[1][3], invViewMatrix[2][3]);
#else
    return mDeformed.xyz;
#endif
]]>
            </CodeInjection>
            <CodeInjection position="GET_PREV_POSITION_VS">
<![CDATA[
#if defined( PIPE_EFFECT )
    float mSpeed = 36.0 * cPrevTime_s;
#else
    float mSpeed = 10.0 * cPrevTime_s;
#endif
    float3 mDeformed = getCustomPositionVS(In, object, mSpeed);
#if defined(SKINNING)
    return skinPrevPoint(mDeformed.xyz, In, object) - float3(invViewMatrix[0][3], invViewMatrix[1][3], invViewMatrix[2][3]);
#else
    return mDeformed.xyz;
#endif
]]>
            </CodeInjection>
            <CodeInjection position="POST_GET_WORLD_POSE_VS">
<![CDATA[
    prevWorldPosition = mul(object.prevModelMatrix, float4(prevPosition, 1));
]]>
            </CodeInjection>
            <CodeInjection position = "LIB_FUNCTION_FS">
<![CDATA[
// 0..1 transitional gradient based on 3 inputs
// mTexture    - cloud nosie style texture
// mGradient   - input source gradient (smooth 0..1 transition)
// mAlphaShift - gradient smoothness (0.1 - almost instant switch, 0.5 - smooth transition)
float alphaGradient(float mTexture, float mGradient, float mAlphaShift){
    return saturate( (-1 + mGradient + mTexture - mAlphaShift) / mAlphaShift);
}
]]>
            </CodeInjection>
            <CodeInjection position = "FS_GLOBALS">
<![CDATA[
    float4 gUV;
    float4 gVertexColor;
    float4 gCloud;
    float  gMask;
    float  gAlpha;
]]>
            </CodeInjection>
            <CodeInjection position = "START_FS">
<![CDATA[
    globals.gVertexColor = In.vs.vertexColor.rgba;
#if defined( PIPE_EFFECT )
    // uvScale used to be here
    float mSpeed     = - 6.0 * cTime_s * object.uvSpeedMult; // this speed is linked to vertexShader deformation speed (mSpeed)
    float mUVscale   = 1.0 ;
#else
    // uvScale used to be here
    float mSpeed      = -2.0 * cTime_s * object.uvSpeedMult;
    float mUVscale    = 3.0 ;
#endif
    globals.gUV.xy    = mUVscale * In.vs.defaultTexCoords  + float2( mSpeed * mUVscale, 0.00 );
    globals.gUV.zw    = mUVscale * In.vs.defaultTexCoords2 + float2( mSpeed * mUVscale, 0.00 );
    // =================================
    globals.gCloud    = tex2D( cloudMask, ( 1 / mUVscale ) * globals.gUV.zw ).rgba;
    globals.gMask     = alphaGradient(globals.gCloud.b,globals.gVertexColor.b,0.05);
    globals.gAlpha    = 1.0;
]]>
            </CodeInjection>
            <CodeInjection position = "GET_UNNORMALIZED_TANGENT_SPACE_NORMAL_FS">
<![CDATA[
 #if defined( NORMAL_MAP )
    #if defined(STATIC_TEST_GEOMETRY)
        float3 mNormalA  = tex2D( normalMap, globals.gUV.xy ).xyz;
        float3 mNormalB  = tex2D( normalMap, globals.gUV.zw ).xyz;
    #else
        float3 mNormalA  = tex2D( normalMap, float3(globals.gUV.xy, object.fillTypeId) ).xyz;
        float3 mNormalB  = tex2D( normalMap, float3(globals.gUV.zw, object.fillTypeId) ).xyz;
    #endif
    float3 mResultNormal = lerp( mNormalA, mNormalB, globals.gMask ) - 0.5;
    return mResultNormal;
 #endif
]]>
            </CodeInjection>
            <CodeInjection position="POST_DIFFUSE_COLOR_FS">
<![CDATA[
#if defined( ALBEDO_MAP )
    #if defined(STATIC_TEST_GEOMETRY)
        float4 mDiffuseA = tex2D( baseMap, globals.gUV.xy ).rgba;
        float4 mDiffuseB = tex2D( baseMap, globals.gUV.zw ).rgba;
    #else
        float4 mDiffuseA = tex2D( baseMap, float3(globals.gUV.xy, object.fillTypeId) ).rgba;
        float4 mDiffuseB = tex2D( baseMap, float3(globals.gUV.zw, object.fillTypeId) ).rgba;
    #endif
    float4 mResultColor = lerp( mDiffuseA, mDiffuseB, globals.gMask );
    diffuseColor   = mResultColor.rgb;
    globals.gAlpha = mResultColor.a;
#endif
]]>
            </CodeInjection>
            <CodeInjection position="POST_GLOSS_COLOR_FS">
<![CDATA[
#if defined(GLOSS_MAP)
    #if defined(STATIC_TEST_GEOMETRY)
        float3 pbrA = tex2D(glossMap, globals.gUV.xy ).xyz;
        float3 pbrB = tex2D(glossMap, globals.gUV.zw ).xyz;
    #else
        float3 pbrA = tex2D(glossMap, float3(globals.gUV.xy, object.fillTypeId) ).xyz;
        float3 pbrB = tex2D(glossMap, float3(globals.gUV.zw, object.fillTypeId) ).xyz;
    #endif
    float3 mResultPBR = lerp( pbrA, pbrB, globals.gMask );
    roughness = 1-mResultPBR.x;
    bakedAO   = mResultPBR.y;
    metalness = mResultPBR.z;
#endif
]]>
            </CodeInjection>
            <CodeInjection position="ALPHA_FS">
<![CDATA[
#if defined( PIPE_EFFECT )
    float2 mUV = In.vs.defaultTexCoords / max( object.controlPoint.x, 0.001);
    //float2 mUV2 = In.vs.defaultTexCoords2/ max( object.controlPoint.x, 0.001);
#else
    float2 mUV = In.vs.defaultTexCoords;
    //float2 mUV2 = In.vs.defaultTexCoords2;
#endif
    /*
    // Extra noise at the bottom of the effect
    float mEnd1 = tex2D(cloudMask,0.5*(mUV+float2(-0.8,0.05)*cTime_s)).b*tex2D(cloudMask,0.76*(mUV+float2(-1.2,0.02)*cTime_s)).b;
    float mEnd2 = tex2D(cloudMask,0.5*(mUV2 +float2(-0.8,0.05)*cTime_s)).b*tex2D(cloudMask,0.76*(mUV2 +float2(-1.2,0.02)*cTime_s)).b;
    float mEnd3 = lerp( mEnd1, mEnd2, globals.gVertexColor.b );
    mEnd3 = 1-mUV.x*mEnd3*mEnd3+0.25*(1-mUV.x);
    float mEndAlpha = globals.gVertexColor.a*mEnd3;
    */
    float mEndAlpha = globals.gVertexColor.a;
    mEndAlpha = alphaGradient(mResultColor.a,mEndAlpha,0.05);
    // =================================
    // -1.0 ==>  1.0
    float2 uv1     = float2( object.fadeProgress.x, 0 ) + ( 1 - mUV )+ 0.05*globals.gCloud.ab ;
    float mFadeIN  = alphaGradient(mResultColor.a, tex2D( fadeMask, uv1 ).r ,0.1);
    //  1.0 ==> -1.0
    float2 uv2     = float2( object.fadeProgress.y, 0 ) + mUV - 0.05*globals.gCloud.ab;
    float mFadeOUT = alphaGradient(mResultColor.a, tex2D( fadeMask, uv2 ).r ,0.1);
    // =================================
    alpha = saturate(mEndAlpha * mFadeIN * mFadeOUT);
]]>
            </CodeInjection>
            <CodeInjection position="FINAL_POS_FS">
<![CDATA[
#if defined( DEBUG_SHOW_PARALLAX )
    oColor.rgb = globals.gMask;
#endif
]]>
            </CodeInjection>
        </CodeInjections>
    </LodLevel>
</CustomShader>
