// standard shader definitions

fpopts = [
    @(if (= $shaderprecision 0) [result "OPTION ARB_precision_hint_fastest;"])
    @(if (= $shaderprecision 2) [result "OPTION ARB_precision_hint_nicest;"])
]

vpstart = [
    !!ARBvp1.0
    @(if $apple_ff_bug [result [
        ATTRIB opos = vertex.position;
        DP4 result.position.x, state.matrix.mvp.row[0], opos;
        DP4 result.position.y, state.matrix.mvp.row[1], opos;
        DP4 result.position.z, state.matrix.mvp.row[2], opos;
        DP4 result.position.w, state.matrix.mvp.row[3], opos;
    ]] [result [
        OPTION ARB_position_invariant;
        ATTRIB opos = vertex.position; 
    ]])
]

fpstart = [
    !!ARBfp1.0
    @fpopts
]

macro normalize [
    DP3 %1.w, %2, %2;
    RSQ %1.w, %1.w;
    MUL %1.xyz, %1.w, %2;
]

fogcoord = [
    TEMP fogplane;
    MAD fogplane, state.matrix.modelview.row[2], program.env[8], program.env[9];
    DP4 result.fogcoord, -opos, fogplane;
]

macro rgbafog [
    TEMP fog;
    SUB fog, state.fog.params.z, fragment.fogcoord.x;
    MUL_SAT fog, fog, state.fog.params.w;
    LRP result.color, fog, %1, %2;
]

vertexparam0 = "program.env[16]"
vertexparam1 = "program.env[17]"
vertexparam2 = "program.env[18]"
vertexparam3 = "program.env[19]"
vertexparam4 = "program.env[20]"
vertexparam5 = "program.env[21]"
vertexparam6 = "program.env[22]"
vertexparam7 = "program.env[23]"

pixelparam0 = "program.env[16]"
pixelparam1 = "program.env[17]"
pixelparam2 = "program.env[18]"
pixelparam3 = "program.env[19]"
pixelparam4 = "program.env[20]"
pixelparam5 = "program.env[21]"
pixelparam6 = "program.env[22]"
pixelparam7 = "program.env[23]"

///////////////////////////////////////////////////
//
// used for any textured polys that don't have a shader set
//
///////////////////////////////////////////////////

shader 0 "default" [        
    @vpstart
    MOV result.texcoord[0], vertex.texcoord[0];
    MOV result.color, vertex.color;
    END
] [
    @fpstart
    TEMP diffuse;
    TEX diffuse, fragment.texcoord[0], texture[0], 2D;
    MUL result.color, fragment.color, diffuse;
    END
]

shader 0 "rgbonly" [
    @vpstart
    MOV result.texcoord[0], vertex.texcoord[0];
    MOV result.color, vertex.color;
    END
] [
    @fpstart
    TEMP diffuse;
    TEX diffuse, fragment.texcoord[0], texture[0], 2D;
    MUL result.color.xyz, fragment.color, diffuse;
    MOV result.color.w, fragment.color;
    END
]

//////////////////////////////////////////////////////////////////////
//
// same, but now without texture sampling (some HUD stuff needs this)
//
//////////////////////////////////////////////////////////////////////

shader 0 "notexture" [        
    @vpstart
    MOV result.color, vertex.color;
    END
] [
    @fpstart
    MOV result.color, fragment.color;
    END
]

//////////////////////////////////////////////////////////////////////
//
// fogged variants of default shaders
//
//////////////////////////////////////////////////////////////////////

shader 0 "fogged" [
    @vpstart
    MOV result.texcoord[0], vertex.texcoord[0];
    MOV result.color, vertex.color;
    @fogcoord
    END 
] [ 
    @fpstart
    OPTION ARB_fog_linear;
    TEMP diffuse;
    TEX diffuse, fragment.texcoord[0], texture[0], 2D;
    MUL result.color, fragment.color, diffuse;
    END
]   

shader 0 "foggednotexture" [
    @vpstart
    MOV result.color, vertex.color;
    @fogcoord
    END
] [
    @fpstart
    OPTION ARB_fog_linear;
    MOV result.color, fragment.color;
    END
]

//////////////////////////////////////////////////////////////////////
//
// for filling the z-buffer only (i.e. multi-pass rendering, OQ)
//
//////////////////////////////////////////////////////////////////////

shader 0 "nocolor" [
    @vpstart
    END
] [
    @fpstart
    END
]

// some OpenGL implementations don't have consistent depth computation between assembly and GLSL shaders
shader 4 "nocolorglsl" [
    void main() { gl_Position = ftransform(); } 
] [
    void main() {}
]

////////////////////////////////////////////////////////
//
// default lightmapped world shader.. does texcoord gen
//
///////////////////////////////////////////////////////

worldshader = [
    shader (if (< (strstr $arg1 "env") 0) 0 2) $arg1 [
        @vpstart
        DP3 result.texcoord[0].x, opos, program.env[0];
        DP3 result.texcoord[0].y, opos, program.env[1];
        DP3 result.texcoord[1].x, state.matrix.texture[1].row[0], vertex.texcoord[1];
        DP3 result.texcoord[1].y, state.matrix.texture[1].row[1], vertex.texcoord[1];

        @arg2

        #pragma CUBE2_shadowmap
        #pragma CUBE2_dynlight
        @fogcoord
        END
    ] [
        @fpstart
        OPTION ARB_fog_linear;
        TEMP diffuse, lm;
        TEX diffuse, fragment.texcoord[0], texture[0], 2D;
        TEX lm,      fragment.texcoord[1], texture[1], 2D;

        #pragma CUBE2_shadowmap lm
        #pragma CUBE2_dynlight lm

        @arg3

        MUL diffuse, diffuse, 2;
        @(if (< $numargs 4) [result [MUL result.color, diffuse, lm;]] [result $arg4])

        #pragma CUBE2_water

        END
    ]
]

worldshader "stdworld" [] []

worldshader "decalworld" [] [
    TEMP decal;
    TEX decal, fragment.texcoord[0], texture[2], 2D;
    LRP diffuse, decal.w, decal, diffuse;
]

setpixelparam 0 1 1 1 // color modulator
worldshader "colorworld" [] [
    MUL diffuse, diffuse, @pixelparam0;
]

setpixelparam 0 1 1 1 // glow color
worldshader "glowworld" [] [] [
    TEMP glow;
    TEX glow, fragment.texcoord[0], texture[2], 2D;
    MUL glow, glow, @pixelparam0;
    MAD result.color, lm, diffuse, glow;
]

setvertexparam 1 1 // pulse frequency (Hz)
worldshader "pulseworld" [
    TEMP k;
    MUL k, program.env[6], @vertexparam1.x;
    FRC k, k;
    MAD k, k, 2, -1;
    ABS result.texcoord[2], k;
] [
    TEMP pulse;
    TEX pulse, fragment.texcoord[0], texture[2], 2D;
    LRP diffuse, fragment.texcoord[2], pulse, diffuse;
]

setvertexparam 0 1 1 1 // glow color
setvertexparam 1 1 // pulse frequency (Hz)
setvertexparam 2 0 0 0 // pulse glow color
worldshader "pulseglowworld" [
    TEMP k, col;
    MUL k, program.env[6], @vertexparam1.x;
    FRC k, k;
    MAD k, k, 2, -1;
    ABS k, k;
    SUB col, @vertexparam2, @vertexparam0; 
    MAD result.texcoord[2], k, col, @vertexparam0;
] [] [
    TEMP glow;
    TEX glow, fragment.texcoord[0], texture[2], 2D;
    MUL glow, glow, fragment.texcoord[2];
    MAD result.color, lm, diffuse, glow;
]

shader 0 "fogworld" [
    @vpstart
    END
] [
    @fpstart
    MOV result.color, state.fog.color;
    END
]

setpixelparam 0 0.2 0.2 0.2 // reflectivity 
worldshader "envworld" [
    MAD result.texcoord[2], vertex.color.yzxw, { -2, 2, 2, 1 }, { 1, -1, -1, 1 };
    TEMP camvec;
    SUB camvec, program.env[4], opos;
    MOV camvec.y, -camvec;
    MOV result.texcoord[3], camvec.yzxw;
] [
    ATTRIB normal = fragment.texcoord[2];
    ATTRIB camvec = fragment.texcoord[3];
    TEMP rvec;
    DP3 rvec, camvec, normal;
    MUL rvec, rvec, normal; 
    MAD rvec, rvec, 2, -camvec; 

    TEMP reflect;
    TEX reflect, rvec, texture[2], CUBE;
] [
    MUL diffuse, diffuse, lm;
    LRP result.color, @pixelparam0, reflect, diffuse;
]

setpixelparam 0 0.2 0.2 0.2 // reflectivity 
worldshader "envworldfast" [
    TEMP camvec, normal, rvec;
    MAD normal, vertex.color, 2, -1;
    SUB camvec, program.env[4], opos;
    DP3 rvec, camvec, normal;
    MUL rvec, rvec, normal; 
    MAD rvec, rvec, 2, -camvec; 
    MOV rvec.y, -rvec;
    MOV result.texcoord[2], rvec.yzxw;
] [
    TEMP reflect;
    TEX reflect, fragment.texcoord[2], texture[2], CUBE;
] [
    MUL diffuse, diffuse, lm;
    LRP result.color, @pixelparam0, reflect, diffuse;
]
altshader envworld stdworld
fastshader envworld envworldfast 2
fastshader envworld stdworld 1

// bumptype:
//    e -> reserve envmap texture slot
//    o -> orthonormalize
//    t -> tangent space cam
//    r -> envmap reflection
//    R -> modulate envmap reflection with spec map
//    s -> spec
//    S -> spec map
//    p -> parallax
//    P -> steep parallax (7 steps)
//    g -> glow
//    G -> pulse glow

btopt = [ >= (strstr $bumptype $arg1) 0 ]

bumpshader = [
    bumptype = $arg2
    normtex = (if (btopt "e") [result "texture[4]"] [result "texture[3]"])
    glowtex = (if (btopt "e") [result "texture[5]"] [result "texture[4]"])
    if (btopt "G") [
        setvertexparam 0 1 1 1 // glow color
        setvertexparam 4 1     // pulse frequency (Hz)
        setvertexparam 5 0 0 0 // pulse glow color
    ] [if (btopt "g") [
        setpixelparam 0 1 1 1  // glow color
    ]]
    if (btopt "S") [
        setpixelparam 1 6 6 6 // spec map multiplier
    ] [if (btopt "s") [
        setpixelparam 1 1 1 1 // spec multiplier
    ]]
    if (|| (btopt "p") (btopt "P")) [
        setpixelparam 2 0.06 -0.03 // parallax scaling
    ]
    if (btopt "R") [
        setpixelparam 3 1 1 1 // reflectivity map multiplier
    ] [if (btopt "r") [
        setpixelparam 3 0.2 0.2 0.2 // reflectivity 
    ]]
    shader (if (btopt "e") [result 3] [result 1]) $arg1 [
        @vpstart
        DP3 result.texcoord[0].x, opos, program.env[0];
        DP3 result.texcoord[0].y, opos, program.env[1];
        // need to store these in Z/W to keep texcoords < 6, otherwise kills performance on Radeons
        // but slows lightmap access in fragment shader a bit, so avoid when possible
        DP3 @(if (|| $minimizetcusage (btopt "r")) [result "result.texcoord[0].z"] [result "result.texcoord[1].x"]), state.matrix.texture[1].row[0], vertex.texcoord[1];
        DP3 @(if (|| $minimizetcusage (btopt "r")) [result "result.texcoord[0].w"] [result "result.texcoord[1].y"]), state.matrix.texture[1].row[1], vertex.texcoord[1];
        @fogcoord
        
        @(if (btopt "o") [result [
            TEMP camv, normal, tangent, binormal, x, y;
            MAD normal, vertex.color, 2, -1;
        
            // TS gram-schmidt orthonormalization, needed for non-90 degree surfaces (expensive, TS only used for eye vector! can remove if no spec/parallax)
            DP3 x, normal, program.env[2];
            MUL x, x, normal;
            SUB tangent, program.env[2], x;
            DP3 x, tangent, program.env[3];
            MUL x, x, tangent;
            DP3 y, normal, program.env[3];
            MUL y, y, normal;
            SUB binormal, program.env[3], x;
            SUB binormal, binormal, y;
        
            @@(if (btopt "t") [result [
                // trans eye vector into TS
                SUB camv, program.env[4], opos;
                DP3 @(if (btopt "r") [result "result.texcoord[1].x"] [result "result.texcoord[2].x"]), camv, tangent;
                DP3 @(if (btopt "r") [result "result.texcoord[1].y"] [result "result.texcoord[2].y"]), camv, binormal;
                DP3 @(if (btopt "r") [result "result.texcoord[1].z"] [result "result.texcoord[2].z"]), camv, normal;
            ]])
            @@(if (btopt "r") [result [
                @@(if (! (btopt "t")) [result [
                    SUB camv, program.env[4], opos;
                    MOV camv.y, -camv;
                    MOV result.texcoord[1], camv.yzxw;
                ]])

                // calculate tangent -> world transform
                MOV result.texcoord[2].x, -tangent.y;
                MOV result.texcoord[2].y, -binormal.y;
                MOV result.texcoord[2].z, -normal.y;

                MOV result.texcoord[3].x, tangent.z;
                MOV result.texcoord[3].y, binormal.z;
                MOV result.texcoord[3].z, normal.z;

                MOV result.texcoord[4].x, tangent.x;
                MOV result.texcoord[4].y, binormal.x;
                MOV result.texcoord[4].z, normal.x;
            ]])
        ]])

        @(if (btopt "G") [result [
            TEMP pulse, pulsecol;
            MUL pulse, program.env[5], @vertexparam4.x;
            FRC pulse, pulse;
            MAD pulse, pulse, 2, -1;
            ABS pulse, pulse;
            SUB pulsecol, @vertexparam5, @vertexparam0; 
            MAD result.texcoord[2].w, pulse, pulsecol, @vertexparam0;
        ]])

        #pragma CUBE2_shadowmap
        #pragma CUBE2_dynlight

        END
    ] [
        @fpstart
        OPTION ARB_fog_linear;
        ATTRIB @(if (|| (btopt "p") (btopt "P")) [result "htc"] [result "dtc"]) = fragment.texcoord[0];
        ATTRIB lmtc = @(if (|| $minimizetcusage (btopt "r")) [result "fragment.texcoord[0]"] [result "fragment.texcoord[1]"]);
        @(if (btopt "r") [result [
            ATTRIB cam = fragment.texcoord[1];
        ]] [if (btopt "t") [result [
            ATTRIB cam = fragment.texcoord[2];
        ]]]) 
        TEMP diffuse, lmc, lmlv, bump, light;

        TEX lmc,  @(if (|| $minimizetcusage (btopt "r")) [result "lmtc.zwzw"] [result "lmtc"]), texture[1], 2D;
        TEX lmlv, @(if (|| $minimizetcusage (btopt "r")) [result "lmtc.zwzw"] [result "lmtc"]), texture[2], 2D;
        MAD lmlv, lmlv, 2, -1;    
    
        @(if (btopt "t") [result [
            TEMP camvts;
            @(normalize camvts cam)
        ]])

        @(if (btopt "p") [result [
            TEMP height;
            TEX height, htc, @@normtex, 2D;
            MAD height.w, height.w, @pixelparam2.x, @pixelparam2.y;    
            TEMP dtc;
            MAD dtc, height.w, camvts, htc;
        ]])

        @(if (btopt "P") [result [
            PARAM step = -0.142857142857143; // 1 / 7
            TEMP duv, dtc, cc;
            RCP duv, camvts.z;
            MUL duv, duv, camvts;
            MUL duv, duv, step;
            MUL duv.xy, duv, @pixelparam2.x;

            MAD dtc.xy, duv, @pixelparam2.y, htc;
            MOV dtc.z, 1.0;
            TEX bump, dtc, @@normtex, 2D; 

            @@(loopconcat i 7 [concatword [
                SLT cc, bump.w, dtc.z;
                MAD dtc, duv, cc, dtc;
                TEX bump, dtc, @@normtex, 2D;
            ]])
        ]])

        TEX diffuse, dtc, texture[0], 2D;
        MUL diffuse, diffuse, 2;

        @(if (! (btopt "P")) [result [TEX bump, dtc, @normtex, 2D;]])
        MAD bump.xyz, bump, 2, -1;

        @(if (btopt "s") [result [
            PARAM specfactor = 32;
            TEMP he;
            ADD he, camvts, lmlv;
            @(normalize he he)
            DP3_SAT he.w, he, bump;
            POW he.w, he.w, specfactor.x;
            @(if (btopt "S") [result [MUL he.w, he, diffuse;]])
            MAD diffuse.xyz, he.w, @pixelparam1, diffuse;
        ]])

        DP3_SAT light, bump, lmlv;
        MUL light, light, lmc;
        MAX light, light, program.env[5];

        #pragma CUBE2_shadowmap light
        #pragma CUBE2_dynlight light

        MUL @(if (|| (btopt "g") (btopt "r")) [result "diffuse.rgb"] [result "result.color"]), diffuse, light;

        @(if (btopt "r") [result [
            TEMP rvec;
            @(if (btopt "t") [result [
                TEMP rvects;
                DP3 rvects, cam, bump;
                MUL rvects, rvects, bump; 
                MAD rvects, rvects, 2, -cam; 

                DP3 rvec.x, rvects, fragment.texcoord[2];
                DP3 rvec.y, rvects, fragment.texcoord[3];
                DP3 rvec.z, rvects, fragment.texcoord[4];
            ]] [result [
                TEMP bumpw;
                DP3 bumpw.x, bump, fragment.texcoord[2];
                DP3 bumpw.y, bump, fragment.texcoord[3];
                DP3 bumpw.z, bump, fragment.texcoord[4];

                DP3 rvec, cam, bumpw;
                MUL rvec, rvec, bumpw; 
                MAD rvec, rvec, 2, -cam; 
            ]])

            TEMP reflect;
            TEX reflect, rvec, texture[3], CUBE;
            @@(if (btopt "R") [result [
                TEMP rmod;
                MUL rmod, diffuse.w, @pixelparam3;
            ]] [result [
                PARAM rmod = @pixelparam3;
            ]])
            LRP @(if (btopt "g") [result "diffuse.rgb"] [result "result.color"]), rmod, reflect, diffuse;
        ]])

        @(if (btopt "g") [result [
            TEMP glow;
            TEX glow, dtc, @@glowtex, 2D;
            MAD result.color, glow, @@(if (btopt "G") [result "fragment.texcoord[2].w"] [result $pixelparam0]), diffuse;
        ]])

        #pragma CUBE2_water

        END
    ]
]

bumpshader "bumpworld"
bumpshader "bumpspecworld" "ots"
fastshader bumpspecworld bumpworld 2

bumpshader "bumpspecmapworld" "otsS"
fastshader bumpspecmapworld bumpworld 2

bumpshader "bumpspecglowworld" "otsg"
bumpshader "bumpspecmapglowworld" "otsSg"
bumpshader "bumpglowworld" "g"
fastshader bumpspecmapglowworld bumpglowworld 2

bumpshader "bumpspecpulseglowworld" "otsgG"
bumpshader "bumpspecmappulseglowworld" "otsSgG"
bumpshader "bumppulseglowworld" "gG"
fastshader bumpspecmappulseglowworld bumppulseglowworld 2

bumpshader "bumpspecparallaxworld" "pots"
bumpshader "bumpspecmapparallaxworld" "potsS"
bumpshader "bumpparallaxworld" "pot"
fastshader bumpspecparallaxworld bumpparallaxworld 2
fastshader bumpspecparallaxworld bumpworld 1
fastshader bumpspecmapparallaxworld bumpparallaxworld 2
fastshader bumpspecmapparallaxworld bumpworld 1

bumpshader "bumpspecparallaxglowworld" "potsg"
bumpshader "bumpspecmapparallaxglowworld" "potsSg"
bumpshader "bumpparallaxglowworld" "potg"
fastshader bumpspecparallaxglowworld bumpparallaxglowworld 2
fastshader bumpspecparallaxglowworld bumpglowworld 1
fastshader bumpspecmapparallaxglowworld bumpparallaxglowworld 2
fastshader bumpspecmapparallaxglowworld bumpglowworld 1

bumpshader "bumpspecparallaxpulseglowworld" "potsgG"
bumpshader "bumpspecmapparallaxpulseglowworld" "potsSgG"
bumpshader "bumpparallaxpulseglowworld" "potgG"
fastshader bumpspecparallaxpulseglowworld bumpparallaxpulseglowworld 2
fastshader bumpspecparallaxpulseglowworld bumppulseglowworld 1
fastshader bumpspecmapparallaxpulseglowworld bumpparallaxpulseglowworld 2
fastshader bumpspecmapparallaxpulseglowworld bumppulseglowworld 1

bumpshader "bumpenvworld" "eor"
bumpshader "bumpenvworldalt" "e"
altshader bumpenvworld bumpenvworldalt
fastshader bumpenvworld bumpenvworldalt 2
bumpshader "bumpenvspecworld" "eotsr"
altshader bumpenvspecworld bumpenvworldalt
fastshader bumpenvspecworld bumpenvworldalt 2
bumpshader "bumpenvspecmapworld" "eotsSrR"
altshader bumpenvspecmapworld bumpenvworldalt
fastshader bumpenvspecmapworld bumpenvworldalt 2

bumpshader "bumpenvglowworld" "eorg"
bumpshader "bumpenvglowworldalt" "eg"
altshader bumpenvglowworld bumpenvglowworldalt
fastshader bumpenvglowworld bumpenvglowworldalt 2
bumpshader "bumpenvspecglowworld" "eotsrg"
altshader bumpenvspecglowworld bumpenvglowworldalt
fastshader bumpenvspecglowworld bumpenvglowworldalt 2
bumpshader "bumpenvspecmapglowworld" "eotsSrRg"
altshader bumpenvspecmapglowworld bumpenvglowworldalt
fastshader bumpenvspecmapglowworld bumpenvglowworldalt 2

bumpshader "bumpenvpulseglowworld" "eorgG"
bumpshader "bumpenvpulseglowworldalt" "egG"
altshader bumpenvpulseglowworld bumpenvpulseglowworldalt
fastshader bumpenvpulseglowworld bumpenvpulseglowworldalt 2
bumpshader "bumpenvspecpulseglowworld" "eotsrgG"
altshader bumpenvspecpulseglowworld bumpenvpulseglowworldalt
fastshader bumpenvspecpulseglowworld bumpenvpulseglowworldalt 2
bumpshader "bumpenvspecmappulseglowworld" "eotsSrRgG"
altshader bumpenvspecmappulseglowworld bumpenvpulseglowworldalt
fastshader bumpenvspecmappulseglowworld bumpenvpulseglowworldalt 2

bumpshader "bumpenvparallaxworld" "epotr"
bumpshader "bumpenvparallaxworldalt" "epot"
altshader bumpenvparallaxworld bumpenvparallaxworldalt
fastshader bumpenvparallaxworld bumpenvparallaxworldalt 2
fastshader bumpenvparallaxworld bumpenvworldalt 1
bumpshader "bumpenvspecparallaxworld" "epotsr"
altshader bumpenvspecparallaxworld bumpenvparallaxworldalt
fastshader bumpenvspecparallaxworld bumpenvparallaxworldalt 2
fastshader bumpenvspecparallaxworld bumpenvworldalt 1
bumpshader "bumpenvspecmapparallaxworld" "epotsSrR"
altshader bumpenvspecmapparallaxworld bumpenvparallaxworldalt
fastshader bumpenvspecmapparallaxworld bumpenvparallaxworldalt 2
fastshader bumpenvspecmapparallaxworld bumpenvworldalt 1

bumpshader "bumpenvparallaxglowworld" "epotrg"
bumpshader "bumpenvparallaxglowworldalt" "epotg"
altshader bumpenvparallaxglowworld bumpenvparallaxglowworldalt
fastshader bumpenvparallaxglowworld bumpenvparallaxglowworldalt 2
fastshader bumpenvparallaxglowworld bumpenvglowworldalt 1
bumpshader "bumpenvspecparallaxglowworld" "epotsrg"
altshader bumpenvspecparallaxglowworld bumpenvparallaxglowworldalt
fastshader bumpenvspecparallaxglowworld bumpenvparallaxglowworldalt 2
fastshader bumpenvspecparallaxglowworld bumpenvglowworldalt 1
bumpshader "bumpenvspecmapparallaxglowworld" "epotsSrRg"
altshader bumpenvspecmapparallaxglowworld bumpenvparallaxglowworldalt
fastshader bumpenvspecmapparallaxglowworld bumpenvparallaxglowworldalt 2
fastshader bumpenvspecmapparallaxglowworld bumpenvglowworldalt 1

bumpshader "bumpenvparallaxpulseglowworld" "epotrgG"
bumpshader "bumpenvparallaxpulseglowworldalt" "epotgG"
altshader bumpenvparallaxpulseglowworld bumpenvparallaxpulseglowpulseglowworldalt
fastshader bumpenvparallaxpulseglowworld bumpenvparallaxpulseglowpulseglowworldalt 2
fastshader bumpenvparallaxpulseglowworld bumpenvpulseglowworldalt 1
bumpshader "bumpenvspecparallaxpulseglowworld" "epotsrgG"
altshader bumpenvspecparallaxpulseglowworld bumpenvparallaxpulseglowworldalt
fastshader bumpenvspecparallaxpulseglowworld bumpenvparallaxpulseglowworldalt 2
fastshader bumpenvspecparallaxpulseglowworld bumpenvpulseglowworldalt 1
bumpshader "bumpenvspecmapparallaxpulseglowworld" "epotsSrRgG"
altshader bumpenvspecmapparallaxpulseglowworld bumpenvparallaxpulseglowworldalt
fastshader bumpenvspecmapparallaxpulseglowworld bumpenvparallaxpulseglowworldalt 2
fastshader bumpenvspecmapparallaxpulseglowworld bumpenvpulseglowworldalt 1

//bumpshader "steepworld" "Pot"

////////////////////////////////////////////////
//
// phong lighting model shader
//
////////////////////////////////////////////////

blurshader = [
    shader 0 $arg1 [
        !!ARBvp1.0
        MOV result.position, vertex.position;
        MOV result.texcoord[0], vertex.texcoord[0];
        END 
    ] [
        @fpstart
        TEMP val, blur1, blur2, tc1, tc2;
        TEX val, fragment.texcoord[0], texture[0], 2D;
        MUL val, val, program.env[0].x;
        @(loopconcat i $arg2 [concatword [
            @(if (= $i 0) [result [
                ADD tc1.xy, fragment.texcoord[0], program.env[1];
                SUB tc2.xy, fragment.texcoord[0], program.env[1];
            ]] [result [
                ADD tc1.@@@@arg3, tc1, program.env[1].@(at "z w" (- $i 1));
                SUB tc2.@@@@arg3, tc2, program.env[1].@(at "z w" (- $i 1));
            ]])
            TEX blur1, tc1, texture[0], 2D;
            TEX blur2, tc2, texture[0], 2D;
            ADD blur1, blur1, blur2;
            MAD @(if (= (+ $i 1) $arg2) [result "result.color"] [result "val"]), blur1, program.env[0].@(at "y z w" $i), val;
        ]])
        END
    ]
]

blurshader blurx1 1 x
blurshader blury1 1 y
blurshader blurx2 2 x
blurshader blury2 2 y
blurshader blurx3 3 x
blurshader blury3 3 y

shader 0 "shadowmapcaster" [
    @vpstart
    TEMP z;
    DP4 z, state.matrix.mvp.row[2], opos;
    SUB result.texcoord[0].x, 1, z;
    MOV result.texcoord[0].y, 1;
    MOV result.texcoord[0].zw, 0;
    END
] [
    @fpstart
    MOV result.color, fragment.texcoord[0];
    END
]

shader 0 "shadowmapreceiver" [
    @vpstart
    TEMP z;
    DP4 z, state.matrix.mvp.row[2], opos;
    SUB result.texcoord[0], program.env[0].y, z;
    @(if $apple_minmax_bug [result "MOV result.texcoord[0].xyw, 0;"])
    END
 ] [
    @fpstart
    MOV result.color, fragment.texcoord[0];
    END
]

// mdltype:
//    e -> envmap
//    n -> normalmap
//    s -> spec
//    m -> masks

mdlopt = [ >= (strstr $modeltype $arg1) 0 ]

modelshader = [
    modeltype = $arg2
    shader 0 $arg1 [
        @vpstart
        ATTRIB onormal = vertex.normal; 
        @(if (mdlopt "n") [result "ATTRIB otangent = vertex.texcoord[1];"])
        PARAM ocampos = program.env[1];
        PARAM lightdir = program.env[0];
        PARAM ambient = program.env[3];

        MOV result.color, vertex.color;
        MOV result.texcoord[0], vertex.texcoord[0];
       
        @(if (|| (mdlopt "e") (mdlopt "s")) [result [
            TEMP camvec;
            SUB camvec, ocampos, opos;
            @(normalize camvec camvec)
        ]])

        @(if (mdlopt "n") [result [
            TEMP obitangent;
            XPD obitangent, onormal, otangent;
            @(normalize obitangent obitangent)
            MUL obitangent, obitangent, otangent.w;

            DP3 result.texcoord[1].x, lightdir, otangent;
            DP3 result.texcoord[1].y, lightdir, obitangent;
            DP3 result.texcoord[1].z, lightdir, onormal;

            @(if (|| (mdlopt "s") (mdlopt "e")) [result [
                DP3 result.texcoord[2].x, camvec, otangent;
                DP3 result.texcoord[2].y, camvec, obitangent;
                DP3 result.texcoord[2].z, camvec, onormal;
            ]])
            
            @(if (mdlopt "e") [result [
                // composition of tangent -> object and object -> world transforms
                //   becomes tangent -> world
                DP3 result.texcoord[3].x, -state.matrix.texture.row[1], otangent;
                DP3 result.texcoord[3].y, -state.matrix.texture.row[1], obitangent;
                DP3 result.texcoord[3].z, -state.matrix.texture.row[1], onormal;

                DP3 result.texcoord[4].x, state.matrix.texture.row[2], otangent;
                DP3 result.texcoord[4].y, state.matrix.texture.row[2], obitangent;
                DP3 result.texcoord[4].z, state.matrix.texture.row[2], onormal;

                DP3 result.texcoord[5].x, state.matrix.texture.row[0], otangent;
                DP3 result.texcoord[5].y, state.matrix.texture.row[0], obitangent;
                DP3 result.texcoord[5].z, state.matrix.texture.row[0], onormal;
            ]])
        ]] [result [
            @(if (mdlopt "s") [result [
                MOV result.texcoord[1], onormal;
                MOV result.texcoord[2], lightdir; 
                ADD result.texcoord[3], lightdir, camvec;
            ]] [result [
                TEMP light;
                DP3 light, onormal, lightdir;
                MUL light, light, 1.5;
                MAX light, light, ambient;
                MUL result.texcoord[1], light, vertex.color;
            ]])
            @(if (mdlopt "e") [result [
                TEMP rvec, invfresnel;
                DP3 invfresnel, camvec, onormal;
                MUL rvec, invfresnel, onormal; 
                MAD rvec, rvec, 2, -camvec;
                DP3 result.texcoord[4].x, -state.matrix.texture.row[1], rvec;
                DP3 result.texcoord[4].y, state.matrix.texture.row[2], rvec;
                DP3 result.texcoord[4].z, state.matrix.texture.row[0], rvec;
                MAX invfresnel, invfresnel, 0;
                MAD result.texcoord[4].w, program.env[6].x, invfresnel, program.env[6].y;
            ]])
        ]])

        @fogcoord
        END
    ] [
        @fpstart
        OPTION ARB_fog_linear;
        ATTRIB dtc = fragment.texcoord[0];
        @(if (mdlopt "n") [result "ATTRIB lightdir = fragment.texcoord[1];"])
        @(if (! (|| (mdlopt "n") (mdlopt "s"))) [result "ATTRIB color = fragment.texcoord[1];"])
        @(if (mdlopt "s") [result [
            @(if (! (mdlopt "n")) [result [
                ATTRIB lightdir = fragment.texcoord[2];
            ]])
            PARAM specfactor = 128;
            PARAM specintensity = program.env[2];
        ]])
        PARAM ambient = program.env[3];
        PARAM glowscale = program.env[4];
        TEMP diffuse, light;

        TEX diffuse, dtc, texture[0], 2D;

        @(if (mdlopt "n") [result [
            TEMP normal;
            TEX normal, dtc, texture[3], 2D;
            MAD normal, normal, 2, -1;

            @(if (|| (mdlopt "e") (mdlopt "s")) [result [
                TEMP camvec;
                @(normalize camvec fragment.texcoord[2])
            ]])
        ]])

        @(if (mdlopt "s") [result [
            TEMP spec, halfangle;
            @(if (mdlopt "n") [result [
                ADD halfangle, lightdir, camvec;
                @(normalize halfangle halfangle)
            ]] [result [
                TEMP normal;
                @(normalize halfangle fragment.texcoord[3])
                @(normalize normal fragment.texcoord[1])
            ]])
            DP3_SAT spec, halfangle, normal;
            POW spec, spec.x, specfactor.x;
            MUL spec, spec, specintensity;
        ]])

        @(if (|| (mdlopt "n") (mdlopt "s")) [result [
            DP3_SAT light, normal, lightdir;
            MUL light.rgb, light, 1.5;
            MAX light, light, ambient;
        ]])

        @(if (mdlopt "m") [result [
            TEMP masks;
            TEX masks, dtc, texture[1], 2D;
                
            @(if (mdlopt "s") [result "MUL spec, spec, masks.r;"])   // specmap in red channel
        ]])
        
        @(if (mdlopt "s") [result [
            MAD light, light, diffuse, spec;
            MUL @(if (|| (mdlopt "m") (mdlopt "e")) [result "light"] [result "result.color"]), light, fragment.color; 
        ]] [if (mdlopt "n") [result [
            MUL light, light, diffuse;
            MUL @(if (|| (mdlopt "m") (mdlopt "e")) [result "light"] [result "result.color"]), light, fragment.color;
        ]] [result [
            MUL @(if (|| (mdlopt "m") (mdlopt "e")) [result "light"] [result "result.color"]), color, diffuse;
        ]]])

        @(if (mdlopt "m") [result [
            TEMP glow;
            MUL glow, diffuse, glowscale;

            @(if (mdlopt "e") [result [
                LRP light, masks.g, glow, light;

                TEMP reflect;
                @(if (mdlopt "n") [result [
                    TEMP invfresnel, rvects, rvec;
                    DP3 invfresnel, camvec, normal;
                    MUL rvects, invfresnel, normal; 
                    MAD rvects, rvects, 2, -camvec; 

                    DP3 rvec.x, rvects, fragment.texcoord[3];
                    DP3 rvec.y, rvects, fragment.texcoord[4];
                    DP3 rvec.z, rvects, fragment.texcoord[5];

                    MAX invfresnel, invfresnel, 0;
                    MAD invfresnel, program.env[6].x, invfresnel, program.env[6].y;

                    TEX reflect, rvec, texture[2], CUBE;
                    MUL masks.b, masks.b, invfresnel; // envmap mask in blue channel
                ]] [result [
                    TEX reflect, fragment.texcoord[4], texture[2], CUBE;
                    MUL masks.b, masks.b, fragment.texcoord[4].w; // envmap mask in blue channel
                ]])
                LRP result.color, masks.b, reflect, light;
            ]] [result [
                LRP result.color, masks.g, glow, light;
            ]])   

            MUL result.color.a, diffuse.a, fragment.color.a;
        ]])

        END
    ]
]

modelshader "stdmodel" "s"
modelshader "masksmodel" "sm"
modelshader "envmapmodel" "sme"
altshader envmapmodel masksmodel

modelshader "bumpmodel" "ns"
modelshader "bumpmasksmodel" "nsm"
modelshader "bumpenvmapmodel" "nsme"
altshader bumpenvmapmodel bumpmasksmodel

////////////////////////////////////////////////
//
// gourad lighting model shader: cheaper, non-specular version for vegetation etc. gets used when spec==0
//
////////////////////////////////////////////////

modelshader "nospecmodel" ""
modelshader "masksnospecmodel" "m"
modelshader "envmapnospecmodel" "me"
altshader envmapnospecmodel masksnospecmodel
fastshader stdmodel nospecmodel 1
fastshader masksmodel masksnospecmodel 1
fastshader envmapmodel envmapnospecmodel 1

modelshader "bumpnospecmodel" "n"
modelshader "bumpmasksnospecmodel" "nm"
modelshader "bumpenvmapnospecmodel" "nme"
altshader bumpenvmapnospecmodel bumpmasksnospecmodel
fastshader bumpmodel bumpnospecmodel 1
fastshader bumpmasksmodel bumpmasksnospecmodel 1
fastshader bumpenvmapmodel bumpenvmapnospecmodel 1

// model shadows

shader 0 "dynshadow" [
    @vpstart
    MOV result.color, vertex.color;
    @fogcoord
    END
] [
    @fpstart
    OPTION ARB_fog_linear;
    MOV result.color, fragment.color;
    END
]

////////////////////////////////////////////////
//
// full screen shaders: 
//
////////////////////////////////////////////////

fsvs = [
    !!ARBvp1.0
    MOV result.position, vertex.position;   // woohoo, no mvp :) 
    MOV result.texcoord[0], vertex.texcoord[0];
]

fsps = [
    @fpstart
    TEMP sample;
    TEX sample, fragment.texcoord[0], texture[0], RECT;
]

setup4corners = [
    ADD result.texcoord[1], vertex.texcoord[0], { -1.5, -1.5, 0, 0 };        
    ADD result.texcoord[2], vertex.texcoord[0], {  1.5, -1.5, 0, 0 };        
    ADD result.texcoord[3], vertex.texcoord[0], { -1.5,  1.5, 0, 0 };        
    ADD result.texcoord[4], vertex.texcoord[0], {  1.5,  1.5, 0, 0 };        
]

sample4corners = [
    TEMP s00, s02, s20, s22;
    TEX s00, fragment.texcoord[1], texture[0], RECT;
    TEX s02, fragment.texcoord[2], texture[0], RECT;
    TEX s20, fragment.texcoord[3], texture[0], RECT;
    TEX s22, fragment.texcoord[4], texture[0], RECT;
]

// some simple ones that just do an effect on the RGB value...

shader 0 "invert" [ @fsvs END ] [ @fsps SUB result.color, 1, sample;   END ]
shader 0 "gbr"    [ @fsvs END ] [ @fsps MOV result.color, sample.yzxw; END ]
shader 0 "bw"     [ @fsvs END ] [ @fsps DP3 result.color, sample, 0.333; END ]

// sobel

shader 0 "sobel"  [ @fsvs @setup4corners END ] [
    @fsps
    @sample4corners

    TEMP t, u;

    ADD t, s00, s20;
    SUB t, t, s02;
    SUB t, t, s22;
    MUL t, t, t;

    ADD u, s00, s02;
    SUB u, u, s20;
    SUB u, u, s22;
    MUL u, u, u;

    ADD t, t, u;

    ADD result.color, sample, t;
    END
]


// bloom-ish

bloomshader = [
    shader 0 (concatword $arg1 "_scale") [ @fsvs @setup4corners END ] [
        @fsps
        @sample4corners
        TEMP t;
        ADD t, s02, s00;
        ADD t, t, s22;
        ADD t, t, s20;
        ADD t, t, sample;
        MUL result.color, t, 0.2; 
        END
    ]

    shader 0 (concatword $arg1 "_init") [ @fsvs END ] [
        @fsps
        TEMP t;
        MAX t, sample.r, sample.g;
        MAX t, t, sample.b;
        MUL t, t, t;
        MUL result.color, t, sample;
        END
    ]

    shader 0 $arg1 [
        @fsvs
        TEMP tc;
        MOV tc, vertex.texcoord[0];
        @(loopconcat i (- $arg2 1) [concat "MUL tc, tc, 0.5; MOV result.texcoord[" (+ $i 1) "], tc;"])
        END
    ] [
        @fsps
        TEMP scaled, bloom;
        @(loopconcat i (- $arg2 1) [
            format [
                TEX @(if (> $i 0) [result "scaled"] [result "bloom"]), fragment.texcoord[%1], texture[%1], RECT;
                @(if (> $i 0) [result [
                    ADD bloom, bloom, scaled;
                ]])
            ] (+ $i 1)
        ])
        MAD result.color, bloom, program.env[0].x, sample;
        END
    ]
]

bloomshader bloom1 1
bloomshader bloom2 2
bloomshader bloom3 3
bloomshader bloom4 4
bloomshader bloom5 5
bloomshader bloom6 6
bloomshader bloom 7

////////////////////////////////////////////////
//
// miscellaneous effect shaders: 
//
////////////////////////////////////////////////

// wobbles the vertices of an explosion sphere
// and generates all texcoords 
// and blends the edge color
// and modulates the texture
explosionshader = [
    shader 0 $arg1 [
        !!ARBvp1.0
        ATTRIB opos = vertex.position; 
        OUTPUT spos = result.position;
        
        TEMP wobble; // uses a simple linear oscillation instead of more expensive sinusoidal
        DP3 wobble, opos, program.env[0]; // generate wobble offset based off vertex normal and sphere center
        MAD wobble, program.env[1].w, 0.002, wobble; // wobble frequency
        FRC wobble, wobble; // 0..1
        SUB wobble, wobble, 0.5; // -0.5..0.5
        ABS wobble, wobble; // now oscillates up and down between 0..0.5
        MUL wobble, wobble, 0.5; // wobble amplitude
        
        MAD wobble.xyz, wobble, opos, opos;
        MOV wobble.w, opos.w;
        
        DP4 spos.x, state.matrix.mvp.row[0], wobble; 
        DP4 spos.y, state.matrix.mvp.row[1], wobble; 
        DP4 spos.z, state.matrix.mvp.row[2], wobble; 
        DP4 spos.w, state.matrix.mvp.row[3], wobble;
       
        MOV result.color, vertex.color;

        @arg2 
        
        @fogcoord
        END
    ] [ 
        @fpstart
        OPTION ARB_fog_linear;
        TEMP dtc, diffuse, blend, tint;
        
        TEX dtc, @arg3, texture[0], 2D;
        MAD dtc, dtc, 0.1, fragment.texcoord[0]; // use color texture as noise to distort texcoords
        TEX diffuse, dtc, texture[0], 2D;
        
        TEX blend, fragment.texcoord[1], texture[1], 2D; // get blend factors from modulation texture 
        MAD tint, blend.a, { 0, 0, -0.5, 0 }, { 0, 0, 0.5, 0 }; // blue tint 
        MUL blend, blend.a, 4; // dup alpha into RGB channels + intensify and over saturate

        MAD diffuse, diffuse, blend, tint;
        MUL result.color, diffuse, fragment.color;

        END
    ]
]

explosionshader "explosion2d" [
    TEMP dtc; //blow up the tex coords
    MAD dtc, program.env[1].x, -1.414, 1.768; // -2, 2.5; -> -2*sqrt(0.5), 2.5*sqrt(0.5);
    MUL dtc, dtc, dtc;
    MUL dtc, opos, dtc;
    //MAD dtc, dtc, 0.5, 0.5; centering at 0.5 not really needed for color sample since texture isn't clamped, so can just fold in the multiplication as above
    MAD result.texcoord[0], program.env[1].w, 0.0004, dtc;
    MAD result.texcoord[1], opos, 0.5, 0.5; //using wobble makes it look too spherical at a distance
] "fragment.texcoord[1]"

explosionshader "explosion3d" [
    MOV result.texcoord[0], vertex.texcoord[0];

    TEMP texgen;
    DP4 texgen.x, opos, program.env[2];
    DP4 texgen.y, opos, program.env[3];
    MOV result.texcoord[1], texgen;
    MAD result.texcoord[2], program.env[1].w, -0.0005, texgen;
] "fragment.texcoord[2]"

///////////////////////////////////////////////////
//
// reflective/refractive water shaders:
//
///////////////////////////////////////////////////

watershader = [
    spec = $arg2
    rgbfog = $arg3
    distort = $arg4
    combine = $arg5
    shader 1 $arg1 [
        @vpstart
        TEMP tc;
        PARAM campos = program.env[0];
        PARAM seconds = program.env[1];
        @(if $spec [result "PARAM lightpos = program.env[2];"])

        DP4 result.texcoord[0].x, state.matrix.texture.row[0], opos;
        DP4 result.texcoord[0].y, state.matrix.texture.row[1], opos;
        SUB result.texcoord[0].z, opos.z, program.env[7]; 
        DP4 result.texcoord[0].w, state.matrix.texture.row[3], opos;
        MUL tc, vertex.texcoord[0], 0.1;
        MAD result.texcoord[1], seconds, 0.04, tc;
        MAD result.texcoord[2], seconds, -0.02, tc;
        SUB result.texcoord[3], campos, opos;
        @(if $spec [result "SUB result.texcoord[4], lightpos, opos;"])

        MOV result.color, vertex.color;

        @fogcoord

        END
    ] [
        @fpstart
        @(if $rgbfog [result "OPTION ARB_fog_linear;"])
        TEMP he, light, cam, bump, invfresnel, temp, dudv;

        ATTRIB projtc = fragment.texcoord[0];
        ATTRIB tc1 = fragment.texcoord[1];
        ATTRIB tc2 = fragment.texcoord[2];
        ATTRIB camts = fragment.texcoord[3];
        @(if $spec [result "ATTRIB lightts = fragment.texcoord[4];"])

        @(normalize cam camts)
        @(if $spec [result [
            @(normalize light lightts)
            ADD he, cam, light;
            @(normalize he he)
        ]])

        TEX dudv, tc1, texture[2], 2D;
        MAD dudv.xy, dudv, 2, -1;

        @distort

        @(if $spec [result [
            PARAM specfactor = 96;

            DP3_SAT he, he, bump;
            POW he, he.x, specfactor.w;
    
            MUL light, program.env[4], light.w;
            RCP_SAT light, light.x;
            MAD light, light, -program.env[3], program.env[3];
        ]])

        @combine

        END
    ]
]

reflectivity = [MAD invfresnel, invfresnel, 0.5, 0.5;]

watershader "water" 1 0 [
    MAD temp, dudv, 0.025, tc2; 
    TEX bump, temp, texture[1], 2D;
    MAD bump.xyz, bump, 2, -1;
] [
    TEMP diffuse;
    MUL temp, fragment.color, program.env[5].x;
    MUL diffuse, temp, 0.6;
    DP3_SAT invfresnel, cam, bump;
    @reflectivity
    LRP temp, invfresnel, temp, diffuse;
    MUL temp, fragment.color, program.env[5].x;

    TEMP col;
    MAD col.rgb, he, light, temp; 
    MUL col.a, invfresnel, program.env[5].y;
    @(rgbafog col "{0, 0, 0, 1}")
]
watershader "waterfast" 0 0 [
    MAD temp, dudv, 0.025, tc2; 
    TEX bump, temp, texture[1], 2D;
    MAD bump.xyz, bump, 2, -1;
] [    
    TEMP diffuse;
    MUL temp, fragment.color, program.env[5].x;
    MUL diffuse, temp, 0.6;
    DP3_SAT invfresnel, cam, bump;
    @reflectivity

    TEMP col;
    LRP col.rgb, invfresnel, temp, diffuse;
    MUL col.a, invfresnel, program.env[5].y;
    @(rgbafog col "{0, 0, 0, 1}")
]
fastshader water waterfast 1
altshader water waterfast

watershader "waterreflect" 1 0 [
    TEMP reflect;

    MAD temp, dudv, 0.4, projtc;
    TXP reflect, temp, texture[0], 2D;

    MAD temp, dudv, 0.025, tc2;
    TEX bump, temp, texture[1], 2D;
    MAD bump.xyz, bump, 2, -1;
] [
    DP3_SAT invfresnel, cam, bump;
    @reflectivity
    MUL temp, fragment.color, program.env[5].x;
    LRP temp, invfresnel, temp, reflect;

    TEMP col;
    MAD col.rgb, he, light, temp;
    MUL col.a, invfresnel, program.env[5].y;
    @(rgbafog col "program.env[6]")
]
watershader "waterreflectfast" 0 0 [
    TEMP reflect;

    MAD temp, dudv, 0.4, projtc;
    TXP reflect, temp, texture[0], 2D;

    MAD temp, dudv, 0.025, tc2;
    TEX bump, temp, texture[1], 2D;
    MAD bump.xyz, bump, 2, -1;
] [
    DP3_SAT invfresnel, cam, bump;
    @reflectivity
    MUL temp, fragment.color, program.env[5].x;

    TEMP col;
    LRP col.rgb, invfresnel, temp, reflect;
    MUL col.a, invfresnel, program.env[5].y;
    @(rgbafog col "program.env[6]")
]
fastshader waterreflect waterreflectfast 2
altshader waterreflect waterreflectfast

watershader "waterrefract" 1 1 [
    TEMP reflect, refract;

    MAD temp, dudv, 0.025, tc2;
    TEX bump, temp, texture[1], 2D;
    MAD bump.xyz, bump, 2, -1;
    TEX dudv, temp, texture[2], 2D;
    MAD dudv.xy, dudv, 2, -1;

    RCP temp.w, projtc.w;
    MUL temp.xy, projtc, temp.wwww; 
    MAD temp.xy, dudv, 0.01, temp;

    TEX reflect, temp, texture[0], 2D;
    TEX refract, temp, texture[3], 2D;
] [
    DP3_SAT invfresnel, cam, bump;
    @reflectivity
    LRP temp, invfresnel, refract, reflect;
    MAD result.color, he, light, temp;
]
watershader "waterrefractfast" 0 1 [
    TEMP reflect, refract;

    MAD temp, dudv, 0.4, projtc;
    TXP reflect, temp, texture[0], 2D;
    TXP refract, temp, texture[3], 2D;

    MAD temp, dudv, 0.025, tc2;
    TEX bump, temp, texture[1], 2D;
    MAD bump.xyz, bump, 2, -1;
] [
    DP3_SAT invfresnel, cam, bump;
    @reflectivity
    LRP result.color, invfresnel, refract, reflect;
]
fastshader waterrefract waterrefractfast 2
altshader waterrefract waterrefractfast

watershader "waterfade" 1 1 [
    TEMP distort, reflect, refract, fade;
    
    MAD temp, dudv, 0.025, tc2;
    TEX bump, temp, texture[1], 2D;
    MAD bump.xyz, bump, 2, -1;
    TEX dudv, temp, texture[2], 2D;
    MAD dudv.xy, dudv, 2, -1;
    
    RCP temp.w, projtc.w;
    MUL temp.xy, projtc, temp.wwww; 
    MAD distort.xy, dudv, 0.01, temp;

    TEX reflect, distort, texture[0], 2D;
    TEX refract, distort, texture[3], 2D;
    TEX fade.a, temp, texture[3], 2D;
    MAD result.color.a, fade, 4, projtc.z;
] [
    DP3_SAT invfresnel, cam, bump;
    @reflectivity
    LRP temp, invfresnel, refract, reflect;
    MAD result.color.rgb, he, light, temp;
]   
watershader "waterfadefast" 0 1 [
    TEMP reflect, refract, fade;
    
    MAD temp, dudv, 0.4, projtc;
    TXP reflect, temp, texture[0], 2D;
    TXP refract, temp, texture[3], 2D;
    TXP fade.a, projtc, texture[3], 2D;
    MAD result.color.a, fade, 4, projtc.z;

    MAD temp, dudv, 0.025, tc2;
    TEX bump, temp, texture[1], 2D;
    MAD bump.xyz, bump, 2, -1;
] [ 
    DP3_SAT invfresnel, cam, bump;
    @reflectivity
    LRP result.color.rgb, invfresnel, refract, reflect;
]
fastshader waterfade waterfadefast 2
altshader waterfade waterrefract

causticshader = [
    shader 0 $arg1 [
        @vpstart
        DP3 result.texcoord[0].x, opos, state.texgen.object.s;
        DP3 result.texcoord[0].y, opos, state.texgen.object.t;
        @fogcoord
        END
    ] [
        @fpstart
        OPTION ARB_fog_linear;
        @arg2
        END
    ]
]
causticshader caustic [
    TEMP caustic, caustic2;
    TEX caustic, fragment.texcoord[0], texture[0], 2D;
    TEX caustic2, fragment.texcoord[0], texture[1], 2D;
    LRP result.color, program.env[0], caustic2, caustic;
]
causticshader causticfast [TEX result.color, fragment.texcoord[0], texture[0], 2D;]
fastshader caustic causticfast 2
// bug on Intel driver prevents parsing of state.texgen
if (! (isshaderdefined caustic)) [caustics 0]

shader 0 "lava" [
    @vpstart
    MOV result.texcoord[0], vertex.texcoord[0];
    MOV result.color, vertex.color;
    @fogcoord
    END
] [
    @fpstart
    OPTION ARB_fog_linear;
    TEMP diffuse;
    TEX diffuse, fragment.texcoord[0], texture[0], 2D;
    MUL diffuse, diffuse, 2;
    MUL result.color, fragment.color, diffuse;
    END
]

shader 0 "glass" [
    @vpstart
    PARAM campos = program.env[0];
    ATTRIB normal = vertex.normal;
    TEMP camvec, rvec, tmp;
    SUB camvec, campos, opos;
    MOV result.texcoord[0], camvec;
    DP3 tmp, camvec, normal;
    MUL tmp, tmp, normal;
    MAD rvec, tmp, 2, -camvec; 
    MOV rvec.y, -rvec;
    MOV result.texcoord[1], rvec.yzxw;
    MOV result.texcoord[2], normal;
    MOV result.color, vertex.color;
    @fogcoord
    END 
] [ 
    @fpstart
    ATTRIB camvec = fragment.texcoord[0];
    ATTRIB rvec = fragment.texcoord[1];
    ATTRIB normal = fragment.texcoord[2];

    TEMP reflect;
    TEX reflect, rvec, texture[0], CUBE;
    
    TEMP invfresnel;
    @(normalize invfresnel camvec)
    DP3 invfresnel, invfresnel, normal;
    MAX invfresnel, invfresnel, 0.70;

    TEMP col;
    MUL col, fragment.color, 0.05;
    LRP col.rgb, invfresnel, col, reflect;
    MUL col.a, invfresnel, 0.95;
 
    @(rgbafog col "{0, 0, 0, 1}")
    END
]
shader 0 "glassfast" [
    @vpstart
    PARAM campos = program.env[0];
    ATTRIB normal = vertex.normal;
    TEMP camvec, rvec, tmp;
    SUB camvec, campos, opos;
    DP3 tmp, camvec, normal;
    MUL tmp, tmp, normal;
    MAD rvec, tmp, 2, -camvec; 
    MOV rvec.y, -rvec;
    MOV result.texcoord[0], rvec.yzxw;
    MOV result.color, vertex.color;
    @fogcoord
    END 
] [ 
    @fpstart
    ATTRIB rvec = fragment.texcoord[0];

    TEMP reflect;
    TEX reflect, rvec, texture[0], CUBE;
    
    PARAM invfresnel = 0.75;
    TEMP col;
    MUL col, fragment.color, 0.05;
    LRP col.rgb, invfresnel, col, reflect;
    MUL col.a, invfresnel, 0.95;

    @(rgbafog col "{0, 0, 0, 1}")
    END
]
fastshader glass glassfast 2
altshader glass glassfast

shader 0 "grass" [
    @vpstart
    MOV result.texcoord[0], vertex.texcoord[0];
    MOV result.color, vertex.color;
    @fogcoord
    END
] [
    @fpstart
    OPTION ARB_fog_linear;
    TEMP diffuse;
    TEX diffuse, fragment.texcoord[0], texture[0], 2D;
    MUL diffuse.xyz, diffuse, 2;
    MUL result.color, fragment.color, diffuse;
    END
]

setuniformparam bumpscale 0.06 -0.03
shader 5 glsltest [
    uniform vec4 texgenS, texgenT, camera, orienttangent, orientbinormal, fogselect, fogplane;
    varying vec3 camvts;
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0].st = vec2(dot(gl_Vertex.xyz, texgenS.xyz), dot(gl_Vertex.xyz, texgenT.xyz));
        gl_TexCoord[1].st = vec4(gl_TextureMatrix[1] * gl_MultiTexCoord1).st;
        vec4 wfogplane = vec4(gl_ModelViewMatrix[0].z, gl_ModelViewMatrix[1].z, gl_ModelViewMatrix[2].z, gl_ModelViewMatrix[3].z) * fogselect + fogplane;
        gl_FogFragCoord = dot(-gl_Vertex, wfogplane);

        vec3 x, y, tangent, binormal, camv;
        vec3 normal = gl_Color.xyz * 2.0 - 1.0;

        x = dot(normal, orienttangent.xyz) * normal;
        tangent = orienttangent.xyz - x;
        x = dot(tangent, orientbinormal.xyz) * tangent;   
        y = dot(normal, orientbinormal.xyz) * normal;
        binormal = (orientbinormal.xyz - x) - y;
               
        camv = camera.xyz - gl_Vertex.xyz;                
        camvts = vec3(dot(camv, tangent), dot(camv, binormal), dot(camv, normal));

        #pragma CUBE2_shadowmap
        #pragma CUBE2_dynlight
    }
] [
    varying vec3 camvts;
    uniform vec4 ambient, bumpscale;
    uniform sampler2D diffusemap, lmcolor, lmdir, normalmap;
    void main(void)
    {
        vec4 lmc = texture2D(lmcolor, gl_TexCoord[1].st);
        vec3 lmlv = texture2D(lmdir, gl_TexCoord[1].st).xyz * 2.0 - 1.0;
        vec3 camn = normalize(camvts);

        float steps = mix(5.0, 20.0, camn.z);
        float dh = 1.0 / steps;
        vec2 duv = -camn.xy*bumpscale.x / (camn.z*steps);
        float height = 1.0;

        vec2 dtc = gl_TexCoord[0].st + duv*bumpscale.y;
        vec4 bump = texture2D(normalmap, dtc);

        while(bump.w < height)
        {
            height -= dh;
            dtc += duv;
            bump = texture2D(normalmap, dtc);
        }

        vec4 diffuse = texture2D(diffusemap, dtc) * 2.0;
        vec3 normal = bump.xyz * 2.0 - 1.0;
        
        float intensity = dot(normal, lmlv);
        if(intensity > 0.0)
        {
            steps = mix(10.0, 20.0, lmlv.z);
            dh = 1.0 / steps;
            duv = lmlv.xy*bumpscale.x / (lmlv.z*steps);

            height = bump.w + dh*0.1;
            while(bump.w < height && height < 1.0)
            {
                height += dh;
                dtc += duv;
                bump = texture2D(normalmap, dtc);
            }

            if(bump.w >= height) intensity = 0.0; 
        }

        vec4 light = lmc * clamp(intensity, 0.0, 1.0);
        #pragma CUBE2_shadowmap light
        #pragma CUBE2_dynlight light
        light = max(light, ambient);
        gl_FragColor = diffuse * light;
        float fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale;
        gl_FragColor.rgb = mix(vec3(gl_Fog.color), gl_FragColor.rgb, clamp(fog, 0.0, 1.0));
        #pragma CUBE2_water
    }
]

