// standard shader definitions

lazyshader = [
    defershader $arg1 $arg2 [
        shader @arg1 @arg2 [@@arg3] [@@arg4]
    ]
]

lmcoordscale = (divf 1 32767)

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

shader 4 "default" [
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0] = gl_MultiTexCoord0;
        gl_FrontColor = gl_Color;
    }
] [
    uniform sampler2D tex0;
    void main(void)
    {
        gl_FragColor = gl_Color * texture2D(tex0, gl_TexCoord[0].xy);
    }
]

shader 4 "rect" [ 
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0] = gl_MultiTexCoord0;
        gl_FrontColor = gl_Color;
    }
] [
    #extension GL_ARB_texture_rectangle : enable
    uniform sampler2DRect tex0;
    void main(void)
    {
        gl_FragColor = gl_Color * texture2DRect(tex0, gl_TexCoord[0].xy);
    }
]

shader 4 "cubemap" [ 
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0] = gl_MultiTexCoord0;
        gl_FrontColor = gl_Color;
    }
] [
    uniform samplerCube tex0;
    void main(void)
    {
        gl_FragColor = gl_Color * textureCube(tex0, gl_TexCoord[0].xyz);
    }
]

shader 4 "rgbonly" [ 
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0] = gl_MultiTexCoord0;
        gl_FrontColor = gl_Color;
    }
] [
    uniform sampler2D tex0;
    void main(void)
    {
        gl_FragColor.rgb = gl_Color.rgb * texture2D(tex0, gl_TexCoord[0].xy).rgb;
        gl_FragColor.a   = gl_Color.a;
    }
]

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

shader 4 "notexture" [
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
    }
] [
    void main(void)
    {
        gl_FragColor = gl_Color;
    }
]

shader 4 "notextureglsl" [
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
    }
] [
    void main(void)
    {
        gl_FragColor = gl_Color;
    }
]

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

shader 4 "fogged" [
    #pragma CUBE2_fog
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0] = gl_MultiTexCoord0;
        gl_FrontColor = gl_Color;
    }
] [
    uniform sampler2D tex0;
    void main(void)
    {
        gl_FragColor = gl_Color * texture2D(tex0, gl_TexCoord[0].xy);
    }
]

shader 4 "foggednotexture" [
    #pragma CUBE2_fog
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
    }
] [
    void main(void)
    {
        gl_FragColor = gl_Color;
    }
]

shader 4 "foggednotextureglsl" [
    #pragma CUBE2_fog
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
    }
] [
    void main(void)
    {
        gl_FragColor = gl_Color;
    }
]

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

shader 4 "nocolor" [
    void main() { gl_Position = ftransform(); } 
] [
    void main() {}
]

shader 4 "nocolorglsl" [
    void main() { gl_Position = ftransform(); } 
] [
    void main() {}
]

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

worldshader = [
    stype = 4
    if (>= (strstr $arg1 "env") 0) [stype = (+ $stype 2)]
    shader $stype $arg1 [
        #pragma CUBE2_fog
        @(if (>= $numargs 5) [result $arg5])
        uniform vec4 texgenscroll;
        void main(void)
        {
            gl_Position = ftransform();
            gl_TexCoord[0].xy = gl_MultiTexCoord0.xy + texgenscroll.xy;
            gl_TexCoord[1].xy = gl_MultiTexCoord1.xy * @lmcoordscale;

            @arg2

            #pragma CUBE2_shadowmap
            #pragma CUBE2_dynlight
            #pragma CUBE2_water
        }
    ] [
        @(if (>= $numargs 5) [result $arg5])
        @(if (>= $numargs 6) [result $arg6])
        uniform vec4 colorparams;
        uniform sampler2D diffusemap, lightmap;
        void main(void)
        {
            vec4 diffuse = texture2D(diffusemap, gl_TexCoord[0].xy);   
            vec4 lm = texture2D(lightmap, gl_TexCoord[1].xy);

            #pragma CUBE2_shadowmap lm
            #pragma CUBE2_dynlight lm

            @arg3

            diffuse *= colorparams;
            @(if (|| (< $numargs 4) [=s $arg4 []]) [result [gl_FragColor = diffuse * lm;]] [result $arg4])

            #pragma CUBE2_water
        }
    ]
]

glareworldshader = [
    variantshader (if (< (strstr $arg1 "env") 0) 4 6) $arg1 4 [
        #pragma CUBE2_fog
        @(if (>= $numargs 4) [result $arg4])
        uniform vec4 texgenscroll;
        void main(void)
        {
            gl_Position = ftransform();
            gl_TexCoord[0].xy = gl_MultiTexCoord0.xy + texgenscroll.xy;
            gl_TexCoord[1].xy = gl_MultiTexCoord1.xy * @lmcoordscale;

            @arg2
        }
    ] [
        @(if (>= $numargs 4) [result $arg4])
        @(if (>= $numargs 5) [result $arg5])
        uniform vec4 colorparams;
        void main(void)
        {
            @arg3
        }
    ]
]

worldshader "stdworld" [] []

defershader 4 "decalworld" [
  worldshader "decalworld" [] [
    vec4 diffuse2 = texture2D(decal, gl_TexCoord[0].xy);
    diffuse.rgb = mix(diffuse.rgb, diffuse2.rgb, diffuse2.a);
  ] [] [] [uniform sampler2D decal;]
]

defershader 4 "glowworld" [
  defuniformparam "glowcolor" 1 1 1 // glow color
  worldshader "glowworld" [] [] [
    vec3 glow = texture2D(glowmap, gl_TexCoord[0].xy).rgb;
    glow *= glowcolor.rgb;
    gl_FragColor = diffuse*lm + vec4(glow, 0.0);
  ] [] [uniform sampler2D glowmap;]
  glareworldshader "glowworld" [] [
    vec3 glow = texture2D(glowmap, gl_TexCoord[0].xy).rgb;
    glow *= glowcolor.rgb;
    float k = max(glow.r, max(glow.g, glow.b)); 
    gl_FragColor.rgb = min(k*k*32.0, 1.0) * glow;
    #pragma CUBE2_variantoverride gl_FragColor.a = texture2D(lightmap, gl_TexCoord[1].xy).a; //
    gl_FragColor.a = colorparams.a;
  ] [] [
    uniform sampler2D glowmap; 
    #pragma CUBE2_variant uniform sampler2D lightmap;
  ]
]

defershader 4 "pulseworld" [
  defuniformparam "pulsespeed" 1 // pulse frequency (Hz)
  worldshader "pulseworld" [
    pulse = abs(fract(millis.x * pulsespeed.x)*2.0 - 1.0); 
  ] [
    vec3 diffuse2 = texture2D(decal, gl_TexCoord[0].xy).rgb; 
    diffuse.rgb = mix(diffuse.rgb, diffuse2, pulse);
  ] [] [uniform vec4 millis; varying float pulse;] [uniform sampler2D decal;]
]

defershader 4 "pulseglowworld" [
  defuniformparam "glowcolor" 1 1 1 // glow color
  defuniformparam "pulseglowspeed" 1 // pulse frequency (Hz)
  defuniformparam "pulseglowcolor" 0 0 0 // pulse glow color
  worldshader "pulseglowworld" [
    pulse = mix(glowcolor.rgb, pulseglowcolor.rgb, abs(fract(millis.x * pulseglowspeed.x)*2.0 - 1.0));
  ] [] [
    vec3 glow = texture2D(glowmap, gl_TexCoord[0].xy).rgb;
    gl_FragColor = diffuse*lm + vec4(glow*pulse, 0.0);
  ] [uniform vec4 millis; varying vec3 pulse;] [uniform sampler2D glowmap;]
  glareworldshader "pulseglowworld" [
    pulse = mix(glowcolor.rgb, pulseglowcolor.rgb, abs(fract(millis.x * pulseglowspeed.x)*2.0 - 1.0));
  ] [
    vec3 glow = texture2D(glowmap, gl_TexCoord[0].xy).rgb;
    glow *= pulse;
    float k = max(glow.r, max(glow.g, glow.b)); 
    gl_FragColor.rgb = min(k*k*32.0, 1.0) * glow;
    #pragma CUBE2_variantoverride gl_FragColor.a = texture2D(lightmap, gl_TexCoord[1].xy).a; //
    gl_FragColor.a = colorparams.a;
  ] [uniform vec4 millis; varying vec3 pulse;] [
    uniform sampler2D glowmap; 
    #pragma CUBE2_variant uniform sampler2D lightmap;
  ]
]

shader 4 "fogworld" [
    void main(void)
    {
        gl_Position = ftransform();
        #pragma CUBE2_water
    }
] [
    void main(void)
    {
        gl_FragColor = gl_Fog.color;
        #pragma CUBE2_water
    }
]

shader 4 "noglareworld" [
    void main(void)
    {
        gl_Position = ftransform();
    }
] [
    void main(void)
    {
        gl_FragColor = vec4(0.0);
    }
]

shader 4 "noglareblendworld" [
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0].xy = gl_MultiTexCoord1.xy * @lmcoordscale;
    }
] [
    uniform sampler2D lightmap;
    void main(void)
    {
        gl_FragColor.rgb = vec3(0.0);
        gl_FragColor.a = texture2D(lightmap, gl_TexCoord[0].xy).a;
    }
]

shader 4 "noglarealphaworld" [
    void main(void)
    {
        gl_Position = ftransform();
    }
] [
    uniform vec4 colorparams;
    uniform sampler2D lightmap;
    void main(void)
    {
        gl_FragColor.rgb = vec3(0.0);
        gl_FragColor.a = colorparams.a;
    }
]
 
defershader 6 "envworld" [
  defuniformparam "envscale" 0.2 0.2 0.2 // reflectivity 
  worldshader "envworld" [
    normal = gl_Normal;
    camvec = camera.xyz - gl_Vertex.xyz; 
  ] [
    vec3 reflect = textureCube(envmap, 2.0*normal*dot(camvec, normal) - camvec).rgb;
  ] [
    diffuse *= lm;
    gl_FragColor.rgb = mix(diffuse.rgb, reflect, envscale.rgb);
    gl_FragColor.a = diffuse.a; 
  ] [uniform vec4 camera; varying vec3 normal, camvec;] [uniform samplerCube envmap;]

  defuniformparam "envscale" 0.2 0.2 0.2 // reflectivity 
  worldshader "envworldfast" [
    vec3 camvec = camera.xyz - gl_Vertex.xyz;
    rvec = 2.0*gl_Normal*dot(camvec, gl_Normal) - camvec;
  ] [
    vec3 reflect = textureCube(envmap, rvec).rgb;
  ] [
    diffuse *= lm;
    gl_FragColor.rgb = mix(diffuse.rgb, reflect, envscale.rgb);
    gl_FragColor.a = diffuse.a; 
  ] [uniform vec4 camera; varying vec3 rvec;] [uniform samplerCube envmap;]

  defuniformparam "envscale" 0.2 0.2 0.2 // reflectivity 
  worldshader "envworldalt" [] []

  altshader envworld envworldalt
  fastshader envworld envworldfast 2
  fastshader envworld envworldalt 1
]

shader 4 "depthfxworld" [
    uniform vec4 depthscale, depthoffsets;
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0] = depthoffsets - (gl_ModelViewMatrix * gl_Vertex).z*depthscale;
    }
] [
    void main(void)
    {
        gl_FragColor = gl_TexCoord[0];
    }
]

shader 4 depthfxsplitworld [
    uniform vec4 depthscale, depthoffsets;
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0] = depthoffsets - (gl_ModelViewMatrix * gl_Vertex).z*depthscale;
    }
] [
    void main(void)
    {
        vec4 ranges = vec4(gl_TexCoord[0].x, fract(gl_TexCoord[0].yzw));
        ranges.xy -= ranges.yz*vec2(0.00390625, 0.00390625);
        gl_FragColor = ranges;
    }
]

// 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
//    i -> glare intensity

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

bumpvariantshader = [
    bumptype = $arg2
    stype = (? (btopt "e") 7 5)
    if (! (btopt "i")) [
        if (btopt "G") [
            defuniformparam "glowcolor" 1 1 1 // glow color
            defuniformparam "pulseglowspeed" 1     // pulse frequency (Hz)
            defuniformparam "pulseglowcolor" 0 0 0 // pulse glow color
        ] [if (btopt "g") [
            defuniformparam "glowcolor" 1 1 1  // glow color
        ]]
        if (btopt "S") [
            defuniformparam "specscale" 6 6 6 // spec map multiplier
        ] [if (btopt "s") [
            defuniformparam "specscale" 1 1 1 // spec multiplier
        ]]
        if (|| (btopt "p") (btopt "P")) [
            defuniformparam "parallaxscale" 0.06 -0.03 // parallax scaling
        ]
        if (btopt "R") [
            defuniformparam "envscale" 1 1 1 // reflectivity map multiplier
        ] [if (btopt "r") [
            defuniformparam "envscale" 0.2 0.2 0.2 // reflectivity 
        ]]
    ] [
        if (btopt "s") [stype = (+ $stype 8)]
    ]
    variantshader $stype $arg1 (? (btopt "i") 4 -1) [
        #pragma CUBE2_fog
        uniform vec4 texgenscroll;
        @(if (|| (btopt "t") (btopt "r")) [result [uniform vec4 camera; varying vec3 camvec;]])
        @(if (btopt "G") [result [uniform vec4 millis; varying float pulse;]])
        @(if (btopt "r") [result [varying mat3 world;]]) 
        void main(void)
        {
            gl_Position = ftransform();
            gl_TexCoord[0].xy = gl_MultiTexCoord0.xy + texgenscroll.xy;
            // 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
            @(if (|| $minimizetcusage (btopt "r")) [result [
                gl_TexCoord[0].zw = gl_MultiTexCoord1.yx * @lmcoordscale;
            ]] [result [
                gl_TexCoord[1].xy = gl_MultiTexCoord1.xy * @lmcoordscale;
            ]])

            @(if (btopt "o") [result [
                vec4 tangent = gl_Color*2.0 - 1.0;
                vec3 binormal = cross(gl_Normal, tangent.xyz) * tangent.w;
                @@(if (btopt "t") [result [
                    // trans eye vector into TS
                    vec3 camobj = camera.xyz - gl_Vertex.xyz;
                    camvec = vec3(dot(camobj, tangent.xyz), dot(camobj, binormal), dot(camobj, gl_Normal));
                ]])
                @@(if (btopt "r") [result [
                    @@(if (! (btopt "t")) [result [
                        camvec = camera.xyz - gl_Vertex.xyz;
                    ]])
                    // calculate tangent -> world transform
                    world = mat3(tangent.xyz, binormal, gl_Normal);
                ]])
            ]]) 
        
            @(if (btopt "G") [result [
                pulse = abs(fract(millis.x*pulseglowspeed.x)*2.0 - 1.0);
            ]])

            @(if (|| (! (btopt "i")) (btopt "s")) [result [
                #pragma CUBE2_dynlight
            ]])
            @(if (! (btopt "i")) [result [
                #pragma CUBE2_shadowmap
                #pragma CUBE2_water
            ]])
        }
    ] [
        uniform vec4 colorparams;
        uniform sampler2D diffusemap, lmcolor, lmdir;
        @(if (|| (! (btopt "i")) (btopt "s") (btopt "p") (btopt "P")) [result [uniform sampler2D normalmap;]])
        @(if (|| (btopt "t") (btopt "r")) [result [varying vec3 camvec;]])
        @(if (btopt "g") [result [uniform sampler2D glowmap;]])
        @(if (btopt "G") [result [varying float pulse;]])
        @(if (btopt "r") [result [uniform samplerCube envmap; varying mat3 world;]])
        @(if (|| (! (btopt "i")) (btopt "s")) [result [uniform vec4 ambient;]])
        void main(void)
        {
            #define lmtc @(? (|| $minimizetcusage (btopt "r")) "gl_TexCoord[0].wz" "gl_TexCoord[1].xy")
            @(if (|| (! (btopt "i")) (btopt "s")) [result [
                vec4 lmc = texture2D(lmcolor, lmtc);
                gl_FragColor.a = colorparams.a * lmc.a;
                vec3 lmlv = texture2D(lmdir, lmtc).rgb*2.0 - 1.0;
            ]])
            @(if (btopt "t") [result [vec3 camdir = normalize(camvec);]])
            @(if (btopt "p") [result [
                float height = texture2D(normalmap, gl_TexCoord[0].xy).a;
                vec2 dtc = gl_TexCoord[0].xy + camdir.xy*(height*parallaxscale.x + parallaxscale.y);
            ]])
            @(if (btopt "P") [result [
                const float step = -1.0/7.0;
                vec3 duv = vec3((step*parallaxscale.x/camdir.z)*camdir.xy, step);
                vec3 htc = vec3(gl_TexCoord[0].xy + duv.xy*parallaxscale.y, 1.0);
                vec4 height = texture2D(normalmap, htc.xy);
                @@(loopconcat i 7 [concatword [
                    htc += height.w < htc.z ? duv : vec3(0.0);
                    height = texture2D(normalmap, htc.xy);
                ]])
                #define dtc htc.xy
                #define bump height.xyz    
            ]])
            @(if (|| (btopt "p") (btopt "P")) [] [result [#define dtc gl_TexCoord[0].xy]])

            @(if (|| (! (btopt "i")) (btopt "S")) [result [
                vec4 diffuse = texture2D(diffusemap, dtc);
            ]])
            @(if (! (btopt "i")) [result [
                diffuse.rgb *= colorparams.rgb;
            ]])

            @(if (|| (! (btopt "i")) (btopt "s")) [result [
                @(if (! (btopt "P")) [result [vec3 bump = texture2D(normalmap, dtc).rgb;]])
                bump = bump*2.0 - 1.0;
            ]])

            @(if (btopt "s") [result [
                vec3 halfangle = normalize(camdir + lmlv);
                float spec = pow(clamp(dot(halfangle, bump), 0.0, 1.0), @(? (btopt "i") "128.0" "32.0"));
                @(if (btopt "i") [result [spec = min(spec*64.0, 1.0);]]) 
                @(if (btopt "S") [result [spec *= diffuse.a;]])
                @(if (btopt "i") [result [
                    @(? (btopt "S") "diffuse.rgb" "vec3 diffuse") = specscale.xyz*spec;
                ]] [result [
                    diffuse.rgb += specscale.xyz*spec;
                ]])
            ]])

            @(if (|| (! (btopt "i")) (btopt "s")) [result [
                lmc.rgb = max(lmc.rgb*clamp(dot(lmlv, bump), 0.0, 1.0), ambient.xyz);
                @(if (btopt "i") [result [
                    #pragma CUBE2_dynlight lmc

                    @(? (btopt "g") "diffuse.rgb" "gl_FragColor.rgb") = diffuse.rgb * lmc.rgb;
                ]] [result [
                    #pragma CUBE2_shadowmap lmc
                    #pragma CUBE2_dynlight lmc

                    @(? (|| (btopt "g") (btopt "r")) "diffuse.rgb" "gl_FragColor.rgb") = diffuse.rgb * lmc.rgb;
                ]])
            ]])
               
            @(if (btopt "r") [result [
                vec3 rvec;
                @(if (btopt "t") [result [
                    vec3 rvects = 2.0*bump*dot(camvec, bump) - camvec;
                    rvec = world * rvects;
                ]] [result [
                    vec3 bumpw = world * bump;
                    rvec = 2.0*bumpw*dot(camvec, bumpw) - camvec;
                ]])
                vec3 reflect = textureCube(envmap, rvec).rgb;
                @@(if (btopt "R") [result [
                    vec3 rmod = envscale.xyz*diffuse.a;
                ]] [result [
                    #define rmod envscale.xyz
                ]])
                @(? (btopt "g") "diffuse.rgb" "gl_FragColor.rgb") = mix(diffuse.rgb, reflect, rmod);
            ]])

            @(if (btopt "g") [result [
                vec3 glow = texture2D(glowmap, dtc).rgb;
                @@(if (btopt "G") [result [
                    vec3 pulsecol = mix(glowcolor.xyz, pulseglowcolor.xyz, pulse);
                ]])
                @@(if (btopt "i") [result [
                    glow *= @(? (btopt "G") "pulsecol" "glowcolor.xyz");
                    float k = max(glow.r, max(glow.g, glow.b));
                    k = min(k*k*32.0, 1.0);
                    @(if (btopt "s") [result [
                        gl_FragColor.rgb = glow*k + diffuse.rgb;
                    ]] [result [
                        gl_FragColor.rgb = glow*k;
                        #pragma CUBE2_variantoverride gl_FragColor.a = texture2D(lmcolor, lmtc).a; //
                        gl_FragColor.a = colorparams.a;
                    ]])
                ]] [result [
                    gl_FragColor.rgb = glow * @(? (btopt "G") "pulsecol" "glowcolor.xyz") + diffuse.rgb;
                ]])
            ]])

            @(if (! (btopt "i")) [result [
                #pragma CUBE2_water
            ]])
        }
    ]
]

bumpshader = [
    defershader (if (>= (strstr $arg2 "e") 0) [result 7] [result 5]) $arg1 [
        bumpvariantshader @arg1 @arg2
        if (|| (btopt "g") (btopt "s")) [
            bumpvariantshader @@arg1 (strreplace (concatword @@arg2 "i") "r")
        ]
    ]
]

bumpshader "bumpworld" ""
bumpshader "bumpspecworld" "ots"
fastshader bumpspecworld bumpworld 2
altshader bumpspecworld bumpworld
bumpshader "bumpspecmapworld" "otsS"
fastshader bumpspecmapworld bumpworld 2
altshader bumpspecmapworld bumpworld

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

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

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

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

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

bumpshader "bumpenvworldalt" "e"
bumpshader "bumpenvworld" "eor"
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 "bumpenvglowworldalt" "eg"
bumpshader "bumpenvglowworld" "eorg"
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 "bumpenvpulseglowworldalt" "egG"
bumpshader "bumpenvpulseglowworld" "eorgG"
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 "bumpenvparallaxworldalt" "epot"
altshader bumpenvparallaxworldalt bumpenvworldalt
bumpshader "bumpenvparallaxworld" "epotr"
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 "bumpenvparallaxglowworldalt" "epotg"
altshader bumpenvparallaxglowworldalt bumpenvglowworldalt
bumpshader "bumpenvparallaxglowworld" "epotrg"
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 "bumpenvparallaxpulseglowworldalt" "epotgG"
altshader bumpenvparallaxpulseglowworldalt bumpenvpulseglowworldalt
bumpshader "bumpenvparallaxpulseglowworld" "epotrgG"
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
//
////////////////////////////////////////////////

// skeletal animation for matrices and dual quaternions

skelanimdefs = [
    skelanimlength = (min (- $maxvsuniforms (+ $reservevpparams 10)) $maxskelanimdata)
    result [
        #pragma CUBE2_attrib vweights 6
        #pragma CUBE2_attrib vbones 7
        attribute vec4 vweights; 
        attribute vec4 vbones;
        #pragma CUBE2_uniform animdata
        uniform vec4 animdata[@@skelanimlength];
    ]
]

skelmatanim = [
    result [
        int index = int(vbones.x);
        @(if (= $arg1 1) [result [
            vec4 mx = animdata[index];
            vec4 my = animdata[index+1];
            vec4 mz = animdata[index+2];
        ]] [result [
            vec4 mx = animdata[index] * vweights.x;
            vec4 my = animdata[index+1] * vweights.x;
            vec4 mz = animdata[index+2] * vweights.x;
            index = int(vbones.y);
            mx += animdata[index] * vweights.y;
            my += animdata[index+1] * vweights.y;
            mz += animdata[index+2] * vweights.y;
        ]])
        @(if (>= $arg1 3) [result [
            index = int(vbones.z);
            mx += animdata[index] * vweights.z;
            my += animdata[index+1] * vweights.z;
            mz += animdata[index+2] * vweights.z;
        ]])
        @(if (>= $arg1 4) [result [
            index = int(vbones.w);
            mx += animdata[index] * vweights.w;
            my += animdata[index+1] * vweights.w;
            mz += animdata[index+2] * vweights.w;
        ]])

        vec4 opos = vec4(dot(mx, gl_Vertex), dot(my, gl_Vertex), dot(mz, gl_Vertex), gl_Vertex.w);

        @(if $arg2 [result [
            vec3 onormal = vec3(dot(mx.xyz, gl_Normal), dot(my.xyz, gl_Normal), dot(mz.xyz, gl_Normal));
        ]])

        @(if $arg3 [result [
            vec3 otangent = vec3(dot(mx.xyz, vtangent.xyz), dot(my.xyz, vtangent.xyz), dot(mz.xyz, vtangent.xyz));
        ]])
    ]
]

skelquatanim = [
    result [
        int index = int(vbones.x);
        @(if (= $arg1 1) [result [
            vec4 dqreal = animdata[index];
            vec4 dqdual = animdata[index+1];
        ]] [result [
            vec4 dqreal = animdata[index] * vweights.x;
            vec4 dqdual = animdata[index+1] * vweights.x;
            index = int(vbones.y);
            dqreal += animdata[index] * vweights.y;
            dqdual += animdata[index+1] * vweights.y;
            @(if (>= $arg1 3) [result [
                index = int(vbones.z);
                dqreal += animdata[index] * vweights.z;
                dqdual += animdata[index+1] * vweights.z;
            ]])
            @(if (>= $arg1 4) [result [
                index = int(vbones.w);
                dqreal += animdata[index] * vweights.w;
                dqdual += animdata[index+1] * vweights.w;
            ]])
            float len = length(dqreal);
            dqreal /= len;
            dqdual /= len;
        ]])

        vec4 opos = vec4((cross(dqreal.xyz, cross(dqreal.xyz, gl_Vertex.xyz) + gl_Vertex.xyz*dqreal.w + dqdual.xyz) + dqdual.xyz*dqreal.w - dqreal.xyz*dqdual.w)*2.0 + gl_Vertex.xyz, gl_Vertex.w);

        @(if $arg2 [result [
            vec3 onormal = cross(dqreal.xyz, cross(dqreal.xyz, gl_Normal) + gl_Normal*dqreal.w)*2.0 + gl_Normal;
        ]])

        @(if $arg3 [result [
            vec3 otangent = cross(dqreal.xyz, cross(dqreal.xyz, vtangent.xyz) + vtangent.xyz*dqreal.w)*2.0 + vtangent.xyz;
        ]])
    ]
]

// model shadowmapping

shadowmapcastervertexshader = [
    result [
        @(if (>= $numargs 2) [result $arg1])
            uniform vec4 shadowintensity;
        @(if (>= $numargs 2) [result [
            void main(void)
            {
                @arg2
                gl_Position = gl_ModelViewProjectionMatrix * opos;
        ]] [result [
            void main(void)
            {
                gl_Position = ftransform();
        ]])
                gl_TexCoord[0] = vec4(1.0 - gl_Position.z, 1.0, 0.0, shadowintensity.x);
            }
    ]
]

shader 4 shadowmapcaster (shadowmapcastervertexshader) [
    void main(void)
    {
        gl_FragColor = gl_TexCoord[0];
    }
]
loop i 4 [
    variantshader 4 shadowmapcaster 0 (shadowmapcastervertexshader (skelanimdefs (+ $i 1) 0 0) (skelmatanim (+ $i 1) 0 0)) []
    variantshader 4 shadowmapcaster 1 (shadowmapcastervertexshader (skelanimdefs (+ $i 1) 0 0) (skelquatanim (+ $i 1) 0 0)) []
]

shader 4 "shadowmapreceiver" [
    uniform vec4 shadowmapbias;
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0] = vec4(0.0, 0.0, shadowmapbias.y - gl_Position.z, 0.0); 
    }
] [
    void main(void)
    {
        gl_FragColor = gl_TexCoord[0];
    }
]

// model stencil shadows

notexturemodelvertexshader = [
    result [
        @(if (>= $numargs 2) [result [
            @arg1
            #pragma CUBE2_fog opos
            void main(void)
            {
                @arg2  
                gl_Position = gl_ModelViewProjectionMatrix * opos;
        ]] [result [
            #pragma CUBE2_fog
            void main(void)
            {
                gl_Position = ftransform();
        ]])
                gl_FrontColor = gl_Color;
            }
    ]
]

shader 4 notexturemodel (notexturemodelvertexshader) [
    void main(void)
    {
        gl_FragColor = gl_Color;
    }
]
loop i 4 [
    variantshader 4 notexturemodel 0 (notexturemodelvertexshader (skelanimdefs (+ $i 1) 0 0) (skelmatanim (+ $i 1) 0 0)) []
    variantshader 4 notexturemodel 1 (notexturemodelvertexshader (skelanimdefs (+ $i 1) 0 0) (skelquatanim (+ $i 1) 0 0)) []
]

// mdltype:
//    e -> envmap
//    n -> normalmap
//    s -> spec
//    m -> masks
//    B -> matrix skeletal animation
//    b -> dual-quat skeletal animation
//    i -> glare intensity

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

modelvertexshader = [
    modeltype = $arg1
    result [
        @(if (|| (mdlopt "b") (mdlopt "B")) [skelanimdefs $arg2 1 (mdlopt "n")])
        #pragma CUBE2_fog opos
        @(if (mdlopt "n") [result [
            #pragma CUBE2_attrib vtangent 1
            attribute vec4 vtangent;
        ]])
        uniform vec4 camera, lightdir, lightscale, texscroll;
        @(if (mdlopt "n") [result [
            @(if (mdlopt "e") [result [
                varying vec3 camvec;
                varying mat3 world;
            ]] [result [
                varying vec3 lightvec, halfangle;
            ]])
        ]] [result [
            @(if (mdlopt "s") [result [
                varying vec3 nvec, halfangle;
            ]])
            @(if (mdlopt "e") [result [
                uniform vec4 envmapscale;
                varying vec3 rvec;
                varying float rmod;
            ]])
        ]])
        void main(void)
        {
            @(if (mdlopt "B") [skelmatanim $arg2 1 (mdlopt "n")])
            @(if (mdlopt "b") [skelquatanim $arg2 1 (mdlopt "n")])
            @(if (|| (mdlopt "b") (mdlopt "B")) [result [
                gl_Position = gl_ModelViewProjectionMatrix * opos;
            ]] [result [
                gl_Position = ftransform();
                #define opos gl_Vertex
                #define onormal gl_Normal
                #define otangent vtangent.xyz
            ]])

            @(if (|| (mdlopt "n") (mdlopt "s") (mdlopt "i")) [result [
                gl_FrontColor = gl_Color;
            ]])
            gl_TexCoord[0].xy = gl_MultiTexCoord0.xy + texscroll.yz;
      
            @(if (|| (mdlopt "e") (mdlopt "s")) [result [
                vec3 camdir = normalize(camera.xyz - opos.xyz);
            ]])

            @(if (mdlopt "n") [
                if (mdlopt "e") [result [
                    camvec = mat3(gl_TextureMatrix[0][0].xyz, gl_TextureMatrix[0][1].xyz, gl_TextureMatrix[0][2].xyz) * camdir;
                    // composition of tangent -> object and object -> world transforms
                    //   becomes tangent -> world
                    vec3 wnormal = mat3(gl_TextureMatrix[0][0].xyz, gl_TextureMatrix[0][1].xyz, gl_TextureMatrix[0][2].xyz) * onormal;
                    vec3 wtangent = mat3(gl_TextureMatrix[0][0].xyz, gl_TextureMatrix[0][1].xyz, gl_TextureMatrix[0][2].xyz) * otangent;
                    world = mat3(wtangent, cross(wnormal, wtangent) * vtangent.w, wnormal);
                ]] [result [
                    vec3 obitangent = cross(onormal, otangent) * vtangent.w;
                    lightvec = vec3(dot(lightdir.xyz, otangent), dot(lightdir.xyz, obitangent), dot(lightdir.xyz, onormal));
                    @(if (mdlopt "s") [result [
                        vec3 halfdir = lightdir.xyz + camdir; 
                        halfangle = vec3(dot(halfdir, otangent), dot(halfdir, obitangent), dot(halfdir, onormal));
                    ]])
                ]]
            ] [result [
                @(if (mdlopt "s") [result [
                    nvec = onormal; 
                    halfangle = lightdir.xyz + camdir;
                ]] [if (! (mdlopt "i")) [result [
                    float intensity = dot(onormal, lightdir.xyz);
                    gl_FrontColor = vec4(gl_Color.rgb*clamp(intensity*(intensity*lightscale.x + lightscale.y) + lightscale.z, 0.0, 1.0), gl_Color.a);
                ]]])
                @(if (mdlopt "e") [result [
                    float invfresnel = dot(camdir, onormal);
                    rvec = mat3(gl_TextureMatrix[0][0].xyz, gl_TextureMatrix[0][1].xyz, gl_TextureMatrix[0][2].xyz) * (2.0*invfresnel*onormal - camdir);
                    rmod = envmapscale.x*max(invfresnel, 0.0) + envmapscale.y;    
                ]])
            ]])
        }
    ] 
]

modelfragmentshader = [
    modeltype = $arg1
    result [
        @(if (mdlopt "n") [result [
            @(if (mdlopt "e") [result [
                #define lightvec lightdirworld.xyz
                uniform vec4 lightdirworld, envmapscale;
                varying vec3 camvec;
                varying mat3 world;
            ]] [result [
                varying vec3 lightvec, halfangle;
            ]])
        ]] [result [
            @(if (mdlopt "s") [result [
                #define lightvec lightdir.xyz
                uniform vec4 lightdir;
                varying vec3 nvec, halfangle;
            ]])
            @(if (mdlopt "e") [result [
                varying vec3 rvec;
                varying float rmod;
            ]])
        ]])
        @(if (&& (|| (mdlopt "s") (mdlopt "n")) (! (mdlopt "i"))) [result [uniform vec4 lightscale;]])
        @(if (|| (mdlopt "s") (mdlopt "m")) [result [uniform vec4 maskscale;]])
        uniform sampler2D tex0;
        @(if (mdlopt "m") [result [uniform sampler2D tex1;]])
        @(if (mdlopt "e") [result [uniform samplerCube tex2;]])
        @(if (mdlopt "n") [result [uniform sampler2D tex3;]])
        void main(void)
        {
            vec4 light = texture2D(tex0, gl_TexCoord[0].xy);
            light.rgb *= 2.0;

            @(if (mdlopt "m") [result [
                vec3 masks = texture2D(tex1, gl_TexCoord[0].xy).rgb;
                vec3 glow = light.rgb * maskscale.y;
            ]])

            @(if (mdlopt "n") [result [
                vec3 normal = texture2D(tex3, gl_TexCoord[0].xy).rgb - 0.5;
                @(if (mdlopt "e") [result [
                    normal = world * normal;
                ]])
                normal = normalize(normal);
            ]])

            @(if (mdlopt "s") [result [
                @(if (mdlopt "n") [
                    if (mdlopt "e") [result [
                        vec3 halfangle = lightvec + camvec;
                    ]]
                ] [result [
                    vec3 normal = normalize(nvec);
                ]])
                float spec = maskscale.x * pow(clamp(dot(normalize(halfangle), normal), 0.0, 1.0), @(? (mdlopt "i") "256.0" "128.0"));
                @(if (mdlopt "m") [result [spec *= masks.r;]])   // specmap in red channel
            ]])

            @(if (mdlopt "i") [
                if (mdlopt "s") [result [
                    spec *= maskscale.z;
                    @(? (mdlopt "m") "light.rgb" "gl_FragColor.rgb") = spec * gl_Color.rgb;
                ]] [
                    if (! (mdlopt "m")) [result [gl_FragColor.rgb = vec3(0.0);]]
                ]
            ] [result [
                @(if (|| (mdlopt "s") (mdlopt "n")) [result [
                    float intensity = dot(normal, lightvec);
                    light.rgb *= clamp(intensity*(intensity*lightscale.x + lightscale.y) + lightscale.z, 0.0, 1.0);
                ]])
                @(if (mdlopt "s") [result [
                    light.rgb += spec;
                ]])
                @(if (mdlopt "m") [result [
                    light.rgb *= gl_Color.rgb;
                ]] [result [
                    gl_FragColor = light * gl_Color;
                ]])
            ]])

            @(if (mdlopt "m") [result [
                @(if (mdlopt "e") [result [
                    light.rgb = mix(light.rgb, glow, masks.g); // glow mask in green channel
                
                    @(if (mdlopt "n") [result [
                        vec3 camn = normalize(camvec);
                        float invfresnel = dot(camn, normal);
                        vec3 rvec = 2.0*invfresnel*normal - camn;
                        float rmod = envmapscale.x*max(invfresnel, 0.0) + envmapscale.y;
                    ]])
                    vec3 reflect = textureCube(tex2, rvec).rgb; 
                    gl_FragColor.rgb = mix(light.rgb, reflect, rmod*masks.b); // envmap mask in blue channel
                ]] [if (mdlopt "i") [result [
                    float k = min(masks.g*masks.g*maskscale.w, 1.0); // glow mask in green channel
                    gl_FragColor.rgb = @(? (mdlopt "s") "glow*k + light.rgb" "glow*k");
                ]] [result [
                    gl_FragColor.rgb = mix(light.rgb, glow, masks.g); // glow mask in green channel
                ]]])
            ]])

            @(if (|| (mdlopt "i") (mdlopt "m")) [result [
                gl_FragColor.a = light.a * gl_Color.a;
            ]])
        }
    ]
]

modelanimshader = [
    fraganimshader = (? (> $arg2 0) $arg2)
    variantshader 4 $arg1 $arg2 (modelvertexshader (concatword "B" $arg3) $arg4) $fraganimshader
    variantshader 4 $arg1 (+ $arg2 1) (modelvertexshader (concatword "b" $arg3) $arg4) $fraganimshader
]
    
modelshader = [
    defershader 4 $arg1 [
        basemodeltype = [@@arg2]
        shader 4 @arg1 (modelvertexshader $basemodeltype) (modelfragmentshader $basemodeltype)
        loop i 4 [
            modelanimshader @@arg1 0 $basemodeltype (+ $i 1)
        ]
        glaremodeltype = (strreplace (concatword $basemodeltype "i") "e") 
        if (< (strstr $glaremodeltype "s") 0) [glaremodeltype = (strreplace $glaremodeltype "n")]
        variantshader 4 @arg1 2 (modelvertexshader $glaremodeltype) (modelfragmentshader $glaremodeltype)
        loop i 4 [
            modelanimshader @@arg1 2 $glaremodeltype (+ $i 1)
        ]
    ]
]

////////////////////////////////////////////////
//
// 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

modelshader "bumpnospecmodel" "n"
modelshader "bumpmasksnospecmodel" "nm"
modelshader "bumpenvmapnospecmodel" "nme"
altshader bumpenvmapnospecmodel bumpmasksnospecmodel

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

modelshader "stdmodel" "s"
fastshader stdmodel nospecmodel 1
modelshader "masksmodel" "sm"
fastshader masksmodel masksnospecmodel 1
modelshader "envmapmodel" "sme"
altshader envmapmodel masksmodel
fastshader envmapmodel envmapnospecmodel 1

modelshader "bumpmodel" "ns"
fastshader bumpmodel bumpnospecmodel 1
modelshader "bumpmasksmodel" "nsm"
fastshader bumpmasksmodel bumpmasksnospecmodel 1
modelshader "bumpenvmapmodel" "nsme"
altshader bumpenvmapmodel bumpmasksmodel
fastshader bumpenvmapmodel bumpenvmapnospecmodel 1

////////////////////////////////////////////////
//
// separable blur with up to 7 taps
//
////////////////////////////////////////////////

blurshader = [
    shader 4 $arg1 [
        uniform vec4 offsets;
        void main(void)
        {
            gl_Position = gl_Vertex;
            gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
            vec2 tc1 = gl_MultiTexCoord0.xy + offsets.xy;
            vec2 tc2 = gl_MultiTexCoord0.xy - offsets.xy;
            gl_TexCoord[1].xy = tc1;
            gl_TexCoord[2].xy = tc2;
            @(loopconcat i (min (- $arg2 1) 2) [concatword [
                tc1.@@arg3 += offsets.@(at "z w" $i);
                tc2.@@arg3 -= offsets.@(at "z w" $i);
                gl_TexCoord[@@(+ (* $i 2) 3)].xy = tc1;
                gl_TexCoord[@@(+ (* $i 2) 4)].xy = tc2;
            ]])
        } 
    ] [
        @(if (=s $arg4 "2DRect") [result [
            #extension GL_ARB_texture_rectangle : enable
        ]])
        uniform vec4 weights, weights2, offset4, offset5, offset6, offset7;
        uniform @(concatword "sampler" $arg4) tex0;
        void main(void)
        {
            #define texval(coords) @(concatword "texture" $arg4)(tex0, (coords))
            vec4 val = texval(gl_TexCoord[0].xy) * weights.x;
            @(loopconcat i $arg2 [concatword [
                @(if (< $i 3) [result [
                    val += weights.@(at "y z w" $i) * (texval(gl_TexCoord[@@(+ (* $i 2) 1)].xy) + texval(gl_TexCoord[@@(+ (* $i 2) 2)].xy));
                ]] [result [
                    val += weights2.@(at "x y z w" (- $i 3)) * 
                                (texval(gl_TexCoord[0].xy + @(at "offset4 offset5 offset6 offset7" (- $i 3)).xy) +
                                 texval(gl_TexCoord[0].xy - @(at "offset4 offset5 offset6 offset7" (- $i 3)).xy));
                ]])
            ]])
            gl_FragColor = val;
        }
    ]
]

loop i 7 [
    blurshader (format "blurx%1" (+ $i 1)) (+ $i 1) x 2D
    blurshader (format "blury%1" (+ $i 1)) (+ $i 1) y 2D
    if (> $i 0) [
        altshader (format "blurx%1" (+ $i 1)) (format "blurx%1" $i)
        altshader (format "blury%1" (+ $i 1)) (format "blury%1" $i)
    ]
    if $usetexrect [
        blurshader (format "blurx%1rect" (+ $i 1)) (+ $i 1) x 2DRect
        blurshader (format "blury%1rect" (+ $i 1)) (+ $i 1) y 2DRect
        if (> $i 0) [
            altshader (format "blurx%1rect" (+ $i 1)) (format "blurx%1rect" $i)
            altshader (format "blury%1rect" (+ $i 1)) (format "blury%1rect" $i)
        ]
    ]
]

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

fsvs = [
    void main(void)
    {
        gl_Position = gl_Vertex;   // woohoo, no mvp :) 
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
]

fsps = [
    #extension GL_ARB_texture_rectangle : enable
    uniform sampler2DRect tex0; 
    void main(void)
    {
        vec4 sample = texture2DRect(tex0, gl_TexCoord[0].xy);
]

setup4corners = [
    gl_TexCoord[1].xy = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5);
    gl_TexCoord[2].xy = gl_MultiTexCoord0.xy + vec2( 1.5, -1.5);
    gl_TexCoord[3].xy = gl_MultiTexCoord0.xy + vec2(-1.5,  1.5);
    gl_TexCoord[4].xy = gl_MultiTexCoord0.xy + vec2( 1.5,  1.5);
]

sample4corners = [
    vec4 s00 = texture2DRect(tex0, gl_TexCoord[1].xy);
    vec4 s02 = texture2DRect(tex0, gl_TexCoord[2].xy);
    vec4 s20 = texture2DRect(tex0, gl_TexCoord[3].xy);
    vec4 s22 = texture2DRect(tex0, gl_TexCoord[4].xy);
]

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

lazyshader 4 "invert" [ @fsvs } ] [ @fsps gl_FragColor = 1.0 - sample; } ]
lazyshader 4 "gbr"    [ @fsvs } ] [ @fsps gl_FragColor = sample.yzxw; } ]
lazyshader 4 "bw"     [ @fsvs } ] [ @fsps gl_FragColor = vec4(dot(sample.xyz, vec3(0.333))); } ]

// sobel

lazyshader 4 "sobel" [ @fsvs @setup4corners } ] [
    @fsps
    @sample4corners

        vec4 t = s00 + s20 - s02 - s22;
        vec4 u = s00 + s02 - s20 - s22;
        gl_FragColor = sample + t*t + u*u;
    }
]

// rotoscope

lazyshader 4 "rotoscope" [
    uniform vec4 params;
    void main(void)
    {
        gl_Position = gl_Vertex;
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;

        // stuff two sets of texture coordinates into each one to get around hardware attribute limits
        gl_TexCoord[1] = vec4(-1.0, -1.0,  1.0, 0.0)*params.x + gl_MultiTexCoord0.xyyx;
        gl_TexCoord[2] = vec4(-1.0,  0.0, -1.0, 1.0)*params.x + gl_MultiTexCoord0.xyyx;
        gl_TexCoord[3] = vec4(-1.0,  1.0,  0.0, 1.0)*params.x + gl_MultiTexCoord0.xyyx;
        gl_TexCoord[4] = vec4( 0.0, -1.0,  1.0, 1.0)*params.x + gl_MultiTexCoord0.xyyx;
    }
] [
    #extension GL_ARB_texture_rectangle : enable
    uniform sampler2DRect tex0; 
    void main(void)
    {
        #define t11 gl_TexCoord[0]
        #define t00_12 gl_TexCoord[1]
        #define t01_20 gl_TexCoord[2]
        #define t02_21 gl_TexCoord[3]
        #define t10_22 gl_TexCoord[4]
        vec4 c00 = texture2DRect(tex0, t00_12.xy);
        vec4 c01 = texture2DRect(tex0, t01_20.xy);
        vec4 c02 = texture2DRect(tex0, t02_21.xy);
        vec4 c10 = texture2DRect(tex0, t10_22.xy);
        vec4 c11 = texture2DRect(tex0, t11.xy);
        vec4 c12 = texture2DRect(tex0, t00_12.wz);
        vec4 c20 = texture2DRect(tex0, t01_20.wz);
        vec4 c21 = texture2DRect(tex0, t02_21.wz);
        vec4 c22 = texture2DRect(tex0, t10_22.wz);

        vec4 diag1 = c00 - c22;
        vec4 diag2 = c02 - c20;
        vec4 xedge = (c01 - c21)*2.0 + diag1 + diag2;
        vec4 yedge = (c10 - c12)*2.0 + diag1 - diag2;
        xedge *= xedge;
        yedge *= yedge;

        vec4 xyedge = xedge + yedge;
        float sobel = step(max(xyedge.x, max(xyedge.y, xyedge.z)), 0.1);

        float hue = dot(c11.xyz, vec3(1.0));
        c11 /= hue;
        vec3 cc = step(vec3(0.2, 0.8, 1.5), vec3(hue));
        c11 *= dot(cc, vec3(0.5, 0.5, 1.5)); 
        
        gl_FragColor = c11 * max(cc.z, sobel);
        
    }
]

blur3shader = [
    lazyshader 4 $arg1 [ 
        void main(void)
        {
            gl_Position = gl_Vertex;
            gl_TexCoord[0].xy = gl_MultiTexCoord0.xy + vec2(@(if $arg2 -0.5 0.0), @(if $arg3 -0.5 0.0));
            gl_TexCoord[1].xy = gl_MultiTexCoord0.xy + vec2(@(if $arg2  0.5 0.0), @(if $arg3  0.5 0.0));
        }
    ] [
        #extension GL_ARB_texture_rectangle : enable
        uniform sampler2DRect tex0; 
        void main(void)
        {
            gl_FragColor = 0.5*(texture2DRect(tex0, gl_TexCoord[0].xy) + texture2DRect(tex0, gl_TexCoord[1].xy));
        }
    ]
]
blur3shader hblur3 1 0
blur3shader vblur3 0 1

blur5shader = [
    lazyshader 4 $arg1 [ 
        @fsvs 
            gl_TexCoord[1].xy = gl_MultiTexCoord0.xy + vec2(@(if $arg2 -1.333 0.0), @(if $arg3 -1.333 0.0));
            gl_TexCoord[2].xy = gl_MultiTexCoord0.xy + vec2(@(if $arg2  1.333 0.0), @(if $arg3  1.333 0.0));
        }
    ] [
        #extension GL_ARB_texture_rectangle : enable
        uniform sampler2DRect tex0; 
        void main(void)
        {
            gl_FragColor = 0.4*texture2DRect(tex0, gl_TexCoord[0].xy) + 0.3*(texture2DRect(tex0, gl_TexCoord[1].xy) + texture2DRect(tex0, gl_TexCoord[2].xy));
        }
    ]
]
blur5shader hblur5 1 0
blur5shader vblur5 0 1

rotoscope = [
    clearpostfx
    if (>= $numargs 1) [addpostfx rotoscope 0 0 0 $arg1]
    if (>= $numargs 2) [
        if (= $arg2 1) [addpostfx hblur3; addpostfx vblur3]
        if (= $arg2 2) [addpostfx hblur5; addpostfx vblur5]
    ]
]

// bloom-ish

shader 4 "glare" [
    void main(void)
    {
        gl_Position = gl_Vertex;
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
    }
] [
    uniform vec4 glarescale;
    uniform sampler2D tex0; 
    void main(void)
    {
        gl_FragColor = texture2D(tex0, gl_TexCoord[0].xy) * glarescale;
    }
]

lazyshader 4 "bloom_scale" [ @fsvs @setup4corners } ] [
    @fsps
    @sample4corners
        gl_FragColor = 0.2 * (s02 + s00 + s22 + s20 + sample);
    }
]

lazyshader 4 "bloom_init" [ @fsvs } ] [
    @fsps
        float t = max(sample.r, max(sample.g, sample.b));
        gl_FragColor = t*t*sample;
    }
]

bloomshader = [
  defershader 4 $arg1 [
    forceshader "bloom_scale"
    forceshader "bloom_init"
    shader 4 @arg1 [
        void main(void)
        {
            gl_Position = gl_Vertex;
            gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
            vec2 tc = gl_MultiTexCoord0.xy;
            @@(loopconcat i $arg2 [concat [
                tc *= 0.5;
                gl_TexCoord[@@(+ $i 1)].xy = tc;
            ]])
        }
    ] [
        #extension GL_ARB_texture_rectangle : enable
        uniform vec4 params;
        uniform sampler2DRect tex0 @@(loopconcat i $arg2 [format ", tex%1" (+ $i 1)]); 
        void main(void)
        {
            vec4 sample = texture2DRect(tex0, gl_TexCoord[0].xy);
            @@(loopconcat i $arg2 [
                format [
                    @(? (> $i 0) "bloom +=" "vec4 bloom =") texture2DRect(tex%1, gl_TexCoord[%1].xy);
                ] (+ $i 1)
            ])
            gl_FragColor = bloom*params.x + sample;
        }
    ]
  ]
]

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

setupbloom = [
    addpostfx bloom_init 1 1 "+0"
    loop i (- $arg1 1) [
        addpostfx bloom_scale (+ $i 2) (+ $i 2) (concatword "+" (+ $i 1))
    ]
    addpostfx (concatword bloom $arg1) 0 0 (loopconcat i (+ $arg1 1) [result $i]) $arg2
]

bloom = [
    clearpostfx
    if (>= $numargs 1) [setupbloom 6 $arg1]
]

////////////////////////////////////////////////
//
// 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 4 $arg1 [
        #pragma CUBE2_fog
        uniform vec4 center, animstate;
        @(if (>= (strstr $arg1 "3d") 0) [result [uniform vec4 texgenS, texgenT;]])
        @(if (>= (strstr $arg1 "soft") 0) [result [uniform vec4 depthfxparams, depthfxview;]]) 
        void main(void)
        {
            vec4 wobble = vec4(gl_Vertex.xyz*(1.0 + 0.5*abs(fract(dot(gl_Vertex.xyz, center.xyz) + animstate.w*0.002) - 0.5)), gl_Vertex.w);
            @(if (>= (strstr $arg1 "soft") 0) [result [
                vec4 projtc = gl_ModelViewProjectionMatrix * wobble;
                gl_Position = projtc;

                gl_TexCoord[3] = vec4((projtc.xy + projtc.w)*depthfxview.xy, projtc.w, depthfxparams.y - (gl_ModelViewMatrix * wobble).z*depthfxparams.x);
            ]] [result [
                gl_Position = gl_ModelViewProjectionMatrix * wobble;
            ]])

            gl_FrontColor = gl_Color;
        
            @arg2 
        } 
    ] [ 
        @(if (>= (strstr $arg1 "rect") 0) [result [
            #extension GL_ARB_texture_rectangle : enable
            uniform sampler2DRect tex2;
        ]] [result [
            uniform sampler2D tex2;
        ]])
        uniform sampler2D tex0, tex1;
        @(if (>= (strstr $arg1 "soft") 0) [result [uniform vec4 depthfxparams;]]) 
        @(if (>= (strstr $arg1 "soft8") 0) [result [uniform vec4 depthfxselect;]])
        void main(void)
        {
            vec2 dtc = gl_TexCoord[0].xy + texture2D(tex0, @arg3.xy).xy*0.1; // use color texture as noise to distort texcoords
            vec4 diffuse = texture2D(tex0, dtc);
            vec4 blend = texture2D(tex1, gl_TexCoord[1].xy); // get blend factors from modulation texture 
            @(if (>= (strstr $arg1 "glare") 0) [result [
                float k = blend.a*blend.a;
                diffuse.rgb *= k*8.0;
                diffuse.a *= k;
                diffuse.b += k*k;
            ]] [result [
                diffuse *= blend.a*4.0; // dup alpha into RGB channels + intensify and over saturate
                diffuse.b += 0.5 - blend.a*0.5; // blue tint 
            ]])

            @(if (>= (strstr $arg1 "soft") 0) [result [
                gl_FragColor.rgb = diffuse.rgb * gl_Color.rgb;

                #define depthvals @(format "texture%1Proj" (? (>= (strstr $arg1 "rect") 0) "2DRect" "2D"))(tex2, gl_TexCoord[3].xyz)
                @(if (>= (strstr $arg1 "soft8") 0) [result [
                    float depth = dot(depthvals, depthfxselect);
                ]] [result [
                    float depth = depthvals.x*depthfxparams.z;
                ]])
                gl_FragColor.a = diffuse.a * max(clamp(depth - gl_TexCoord[3].w, 0.0, 1.0) * gl_Color.a, depthfxparams.w);
            ]] [result [
                gl_FragColor = diffuse * gl_Color;
            ]])
        }
    ]
]

loop i (if $usetexrect 6 4) [
    explosionshader (concatword "explosion2d" (at ["" "glare" "soft" "soft8" "softrect" "soft8rect"] $i)) [
        //blow up the tex coords
        float dtc = 1.768 - animstate.x*1.414; // -2, 2.5; -> -2*sqrt(0.5), 2.5*sqrt(0.5);
        dtc *= dtc;
        gl_TexCoord[0].xy = animstate.w*0.0004 + dtc*gl_Vertex.xy;
        gl_TexCoord[1].xy = gl_Vertex.xy*0.5 + 0.5; //using wobble makes it look too spherical at a distance
    ] "gl_TexCoord[1]"
    explosionshader (concatword "explosion3d" (at ["" "glare" "soft" "soft8" "softrect" "soft8rect"] $i)) [
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
        vec2 texgen = vec2(dot(texgenS, gl_Vertex), dot(texgenT, gl_Vertex)); 
        gl_TexCoord[1].xy = texgen;
        gl_TexCoord[2].xy = texgen - animstate.w*0.0005;
    ] "gl_TexCoord[2]"
]

shader 4 "particlenotexture" [
    #pragma CUBE2_fog
    uniform vec4 colorscale;
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0] = gl_Color * colorscale;
    } 
] [
    void main(void)
    {
        gl_FragColor = gl_TexCoord[0];
    }
]

particleshader = [
    shader 4 $arg1 [
        #pragma CUBE2_fog
        uniform vec4 colorscale;
        @(if (>= (strstr $arg1 "soft") 0) [result [uniform vec4 depthfxparams, depthfxview;]]) 
        void main(void)
        {
            gl_Position = ftransform();
            gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
            gl_TexCoord[1] = gl_Color * colorscale; 

            @(if (>= (strstr $arg1 "soft") 0) [result [
                vec4 projtc = gl_ModelViewProjectionMatrix * gl_Vertex;
                gl_TexCoord[2].xyz = vec3((projtc.xy + projtc.w) * depthfxview.xy, projtc.w);

                vec2 offset = gl_MultiTexCoord0.xy*2.82842712474619 - 1.4142135623731;
                gl_TexCoord[3].xyz = vec3(offset, 1.0);
                gl_TexCoord[4].xyz = vec3(offset, depthfxparams.y - (gl_ModelViewMatrix * gl_Vertex).z*depthfxparams.x);
            ]])
        }
    ] [
        @(if (>= (strstr $arg1 "soft") 0) [
            if (>= (strstr $arg1 "rect") 0) [result [
                #extension GL_ARB_texture_rectangle : enable
                uniform sampler2DRect tex2;
            ]] [result [
                uniform sampler2D tex2;
            ]]
        ])
        uniform sampler2D tex0;
        @(if (>= (strstr $arg1 "soft") 0) [result [uniform vec4 depthfxparams;]]) 
        @(if (>= (strstr $arg1 "soft8") 0) [result [uniform vec4 depthfxselect;]])
        void main(void)
        {
            vec4 diffuse = texture2D(tex0, gl_TexCoord[0].xy);

            @(if (>= (strstr $arg1 "soft") 0) [result [
                #define depthvals @(format "texture%1Proj" (? (>= (strstr $arg1 "rect") 0) "2DRect" "2D"))(tex2, gl_TexCoord[2].xyz)
                @(if (>= (strstr $arg1 "soft8") 0) [result [
                    float depth = dot(depthvals, depthfxselect);
                ]] [result [
                    float depth = depthvals.x*depthfxparams.z;
                ]])
                diffuse.a *= clamp(depth - dot(gl_TexCoord[3].xyz, gl_TexCoord[4].xyz), 0.0, 1.0);
            ]])

            gl_FragColor = diffuse * gl_TexCoord[1];
        }
    ]     
]

loop i (if $usetexrect 5 3) [
    particleshader (concatword "particle" (at ["" "soft" "soft8" "softrect" "soft8rect"] $i))
]

shader 4 "blendbrush" [
    uniform vec4 texgenS, texgenT;
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
        gl_TexCoord[0].xy = vec2(dot(texgenS, gl_Vertex), dot(texgenT, gl_Vertex));
    }
] [
    uniform sampler2D tex0;
    void main(void)
    {
        gl_FragColor = texture2D(tex0, gl_TexCoord[0].xy) * gl_Color;
    }
]

lazyshader 4 "moviergb" [
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
    }
] [
    #extension GL_ARB_texture_rectangle : enable
    uniform sampler2DRect tex0;
    void main(void)
    {
        gl_FragColor = texture2DRect(tex0, gl_TexCoord[0].xy);
    }
]

lazyshader 4 "movieyuv" [
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
    }
] [
    #extension GL_ARB_texture_rectangle : enable
    uniform sampler2DRect tex0;
    void main(void)
    {
        vec3 sample = texture2DRect(tex0, gl_TexCoord[0].xy).rgb;
        gl_FragColor = vec4(dot(sample, vec3(0.439216, -0.367788, -0.071427)) + 0.501961,
                            dot(sample, vec3(-0.148224, -0.290992, 0.439216)) + 0.501961,
                            dot(sample, vec3(0.256788, 0.504125, 0.097905)) + 0.062745,
                            0.0);
    }
]

lazyshader 4 "moviey" [
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy + vec2(-1.5, 0.0);
        gl_TexCoord[1].xy = gl_MultiTexCoord0.xy + vec2(-0.5, 0.0);
        gl_TexCoord[2].xy = gl_MultiTexCoord0.xy + vec2( 0.5, 0.0);
        gl_TexCoord[3].xy = gl_MultiTexCoord0.xy + vec2( 1.5, 0.0);
    }
] [
    #extension GL_ARB_texture_rectangle : enable
    uniform sampler2DRect tex0;
    void main(void)
    {
        vec3 sample1 = texture2DRect(tex0, gl_TexCoord[0].xy).rgb;
        vec3 sample2 = texture2DRect(tex0, gl_TexCoord[1].xy).rgb;
        vec3 sample3 = texture2DRect(tex0, gl_TexCoord[2].xy).rgb;
        vec3 sample4 = texture2DRect(tex0, gl_TexCoord[3].xy).rgb;
        gl_FragColor = vec4(dot(sample3, vec3(0.256788, 0.504125, 0.097905)) + 0.062745,
                            dot(sample2, vec3(0.256788, 0.504125, 0.097905)) + 0.062745,
                            dot(sample1, vec3(0.256788, 0.504125, 0.097905)) + 0.062745,
                            dot(sample4, vec3(0.256788, 0.504125, 0.097905)) + 0.062745);
    }
]

lazyshader 4 "movieu" [
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy + vec2(-3.0, 0.0);
        gl_TexCoord[1].xy = gl_MultiTexCoord0.xy + vec2(-1.0, 0.0);
        gl_TexCoord[2].xy = gl_MultiTexCoord0.xy + vec2( 1.0, 0.0);
        gl_TexCoord[3].xy = gl_MultiTexCoord0.xy + vec2( 3.0, 0.0);
    }
] [
    #extension GL_ARB_texture_rectangle : enable
    uniform sampler2DRect tex0;
    void main(void)
    {
        vec3 sample1 = texture2DRect(tex0, gl_TexCoord[0].xy).rgb;
        vec3 sample2 = texture2DRect(tex0, gl_TexCoord[1].xy).rgb;
        vec3 sample3 = texture2DRect(tex0, gl_TexCoord[2].xy).rgb;
        vec3 sample4 = texture2DRect(tex0, gl_TexCoord[3].xy).rgb;
        gl_FragColor = vec4(dot(sample3, vec3(-0.148224, -0.290992, 0.43921)) + 0.501961,
                            dot(sample2, vec3(-0.148224, -0.290992, 0.43921)) + 0.501961,
                            dot(sample1, vec3(-0.148224, -0.290992, 0.43921)) + 0.501961,
                            dot(sample4, vec3(-0.148224, -0.290992, 0.43921)) + 0.501961);
    }
]

lazyshader 4 "moviev" [
    void main(void)
    {
        gl_Position = ftransform();
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy + vec2(-3.0, 0.0);
        gl_TexCoord[1].xy = gl_MultiTexCoord0.xy + vec2(-1.0, 0.0);
        gl_TexCoord[2].xy = gl_MultiTexCoord0.xy + vec2( 1.0, 0.0);
        gl_TexCoord[3].xy = gl_MultiTexCoord0.xy + vec2( 3.0, 0.0);
    }
] [
    #extension GL_ARB_texture_rectangle : enable
    uniform sampler2DRect tex0;
    void main(void)
    {
        vec3 sample1 = texture2DRect(tex0, gl_TexCoord[0].xy).rgb;
        vec3 sample2 = texture2DRect(tex0, gl_TexCoord[1].xy).rgb;
        vec3 sample3 = texture2DRect(tex0, gl_TexCoord[2].xy).rgb;
        vec3 sample4 = texture2DRect(tex0, gl_TexCoord[3].xy).rgb;
        gl_FragColor = vec4(dot(sample3, vec3(0.439216, -0.367788, -0.071427)) + 0.501961,
                            dot(sample2, vec3(0.439216, -0.367788, -0.071427)) + 0.501961,
                            dot(sample1, vec3(0.439216, -0.367788, -0.071427)) + 0.501961,
                            dot(sample4, vec3(0.439216, -0.367788, -0.071427)) + 0.501961);
    }
]

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

watershader = [
    specular = $arg2
    rgbfog = $arg3
    distort = $arg4
    combine = $arg5
    lazyshader 4 $arg1 [
        uniform vec4 camera, millis, waterheight;
        @(if $specular [result [uniform vec4 lightpos; varying vec3 lightdir;]])
        varying vec3 camdir;
        void main(void)
        {
            gl_Position = ftransform();
            gl_FrontColor = gl_Color;
            gl_TexCoord[0] = gl_TextureMatrix[0] * gl_Vertex;
            @(if (>= (strstr $arg1 "underwater") 0) [result [
                gl_TexCoord[0].z = waterheight.x - gl_Vertex.z;
            ]] [result [
                gl_TexCoord[0].z = gl_Vertex.z - waterheight.x;
            ]])
            vec2 tc = gl_MultiTexCoord0.xy * 0.1;
            gl_TexCoord[1].xy = tc + millis.x*0.04;
            gl_TexCoord[2].xy = tc - millis.x*0.02;
            camdir = camera.xyz - gl_Vertex.xyz;
            @(if $specular [result [
                lightdir = lightpos.xyz - gl_Vertex.xyz;
            ]])
        }
    ] [
        @(if $rgbfog [result [
            #pragma CUBE2_fog
        ]] [result [
            #pragma CUBE2_fogrgba vec4(0.0, 0.0, 0.0, 1.0)
        ]])
        uniform vec4 depth;
        @(if $specular [result [uniform vec4 lightcolor, lightradius; varying vec3 lightdir;]])
        varying vec3 camdir;
        @(if (>= (strstr $arg1 "env") 0) [result [
            uniform samplerCube tex0;
        ]] [result [
            uniform sampler2D tex0;
        ]]) 
        uniform sampler2D tex1, tex2, tex3;
        void main(void)
        {
            vec3 camvec = normalize(camdir);
            @(if $specular [result [
                vec3 lightvec = normalize(lightdir);
                vec3 halfangle = normalize(camvec + lightvec);
            ]])
                
            vec2 dudv = texture2D(tex2, gl_TexCoord[1].xy).xy*2.0 - 1.0;
        
            @distort
            
            @(if $specular [result [
                float spec = pow(clamp(dot(halfangle, bump), 0.0, 1.0), 96.0);
                vec3 light = lightcolor.xyz * (1.0 - clamp(length(lightdir)/lightradius.x, 0.0, 1.0));
            ]])

            @combine
        }
    ]
]

watershader "waterglare" 1 1 [
    vec3 bump = texture2D(tex1, gl_TexCoord[2].xy + 0.025*dudv).rgb*2.0 - 1.0;
] [
    gl_FragColor = vec4(light*spec*spec*32.0, 0.0);
]
lazyshader 4 "waterglarefast" [
    #pragma CUBE2_fog
    void main(void)
    {
        gl_Position = ftransform();
    }
] [
    void main(void)
    {
        gl_FragColor = vec4(0.0);
    }
]
fastshader waterglare waterglarefast 2
altshader waterglare waterglarefast

lazyshader 4 "underwater" [
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
    }
] [
    #pragma CUBE2_fogrgba vec4(0.0, 0.0, 0.0, 1.0)
    uniform vec4 depth;
    void main(void)
    {    
        gl_FragColor.rgb = 0.8*depth.x*gl_Color.rgb;
        gl_FragColor.a = 0.5*depth.y; 
    }
]

watershader "underwaterrefract" 0 1 [
    dudv = texture2D(tex2, gl_TexCoord[2].xy + 0.025*dudv).xy*2.0 - 1.0;

    gl_FragColor = texture2D(tex3, gl_TexCoord[0].xy/gl_TexCoord[0].w + 0.01*dudv);
] []
watershader "underwaterrefractfast" 0 1 [
    gl_FragColor = texture2DProj(tex3, gl_TexCoord[0] + vec4(0.4*dudv, 0.0, 0.0));
] []
fastshader underwaterrefract underwaterrefractfast 2
altshader underwaterrefract underwaterrefractfast

watershader "underwaterfade" 0 1 [
    dudv = texture2D(tex2, gl_TexCoord[2].xy + 0.025*dudv).xy*2.0 - 1.0;

    vec2 projtc = gl_TexCoord[0].xy/gl_TexCoord[0].w;
    float fade = gl_TexCoord[0].z + 4.0*texture2D(tex3, projtc).a;
    gl_FragColor.a = fade * clamp(gl_FragCoord.z, 0.0, 1.0);
    gl_FragColor.rgb = texture2D(tex3, projtc + 0.01*dudv).rgb; 
] []
watershader "underwaterfadefast" 0 1 [
    gl_FragColor.rgb = texture2DProj(tex3, gl_TexCoord[0] + vec4(0.4*dudv, 0.0, 0.0)).rgb;
    gl_FragColor.a = gl_TexCoord[0].z + 4.0*texture2DProj(tex3, gl_TexCoord[0]).a;
] []
fastshader underwaterfade underwaterfadefast 2
altshader underwaterfade underwaterfadefast

watershader "water" 1 0 [
    vec3 bump = texture2D(tex1, gl_TexCoord[2].xy + 0.025*dudv).rgb*2.0 - 1.0;
] [
    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0);
    gl_FragColor.rgb = gl_Color.rgb*depth.x*mix(0.6, 1.0, invfresnel*0.5+0.5) + spec*light;
    gl_FragColor.a = invfresnel*depth.y;
]
watershader "waterfast" 0 0 [
    vec3 bump = texture2D(tex1, gl_TexCoord[2].xy + 0.025*dudv).rgb*2.0 - 1.0;
] [    
    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0);
    gl_FragColor.rgb = gl_Color.rgb*depth.x*mix(0.6, 1.0, invfresnel*0.5+0.5);
    gl_FragColor.a = invfresnel*depth.y;
]
fastshader water waterfast 1
altshader water waterfast

watershader "waterreflect" 1 0 [
    vec3 reflect = texture2DProj(tex0, gl_TexCoord[0] + vec4(0.4*dudv, 0.0, 0.0)).rgb;
    vec3 bump = texture2D(tex1, gl_TexCoord[2].xy + 0.025*dudv).rgb*2.0 - 1.0;
] [
    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0);
    gl_FragColor.rgb = mix(reflect, gl_Color.rgb*depth.x, invfresnel*0.5+0.5) + spec*light;
    gl_FragColor.a = invfresnel*depth.y;
]
watershader "waterreflectfast" 0 0 [
    vec3 reflect = texture2DProj(tex0, gl_TexCoord[0] + vec4(0.4*dudv, 0.0, 0.0)).rgb;
    vec3 bump = texture2D(tex1, gl_TexCoord[2].xy + 0.025*dudv).rgb*2.0 - 1.0;
] [
    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0);
    gl_FragColor.rgb = mix(reflect, gl_Color.rgb*depth.x, invfresnel*0.5+0.5);
    gl_FragColor.a = invfresnel*depth.y;
]
fastshader waterreflect waterreflectfast 2
altshader waterreflect waterreflectfast

watershader "waterrefract" 1 1 [
    vec2 dtc = gl_TexCoord[2].xy + 0.025*dudv;
    vec3 bump = texture2D(tex1, dtc).rgb*2.0 - 1.0;
    dudv = texture2D(tex2, dtc).xy*2.0 - 1.0;

    vec2 rtc = gl_TexCoord[0].xy/gl_TexCoord[0].w + 0.01*dudv;
    vec3 reflect = texture2D(tex0, rtc).rgb;
    vec3 refract = texture2D(tex3, rtc).rgb;
] [
    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0);
    gl_FragColor = vec4(mix(reflect, refract, invfresnel*0.5+0.5) + spec*light, 0.0);
]
watershader "waterrefractfast" 0 1 [
    vec4 rtc = gl_TexCoord[0] + vec4(0.4*dudv, 0.0, 0.0);
    vec3 reflect = texture2DProj(tex0, rtc).rgb;
    vec3 refract = texture2DProj(tex3, rtc).rgb;
    vec3 bump = texture2D(tex1, gl_TexCoord[2].xy + 0.025*dudv).rgb*2.0 - 1.0;
] [
    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0);
    gl_FragColor = vec4(mix(reflect, refract, invfresnel*0.5+0.5), 0.0);
]
fastshader waterrefract waterrefractfast 2
altshader waterrefract waterrefractfast

watershader "waterfade" 1 1 [
    vec2 dtc = gl_TexCoord[2].xy + 0.025*dudv;
    vec3 bump = texture2D(tex1, dtc).rgb*2.0 - 1.0;
    dudv = texture2D(tex2, dtc).xy*2.0 - 1.0;

    vec2 projtc = gl_TexCoord[0].xy/gl_TexCoord[0].w;
    vec2 rtc = projtc + 0.01*dudv;
    vec3 reflect = texture2D(tex0, rtc).rgb;
    vec3 refract = texture2D(tex3, rtc).rgb;
    float fade = gl_TexCoord[0].z + 4.0*texture2D(tex3, projtc).a;
    gl_FragColor.a = fade * clamp(gl_FragCoord.z, 0.0, 1.0);
] [
    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0);
    gl_FragColor.rgb = mix(reflect, refract, invfresnel*0.5+0.5) + spec*light;
]   
watershader "waterfadefast" 0 1 [
    vec4 rtc = gl_TexCoord[0] + vec4(0.4*dudv, 0.0, 0.0);
    vec3 reflect = texture2DProj(tex0, rtc).rgb;
    vec3 refract = texture2DProj(tex3, rtc).rgb;
    gl_FragColor.a = gl_TexCoord[0].z + 4.0*texture2DProj(tex3, gl_TexCoord[0]).a;
    vec3 bump = texture2D(tex1, gl_TexCoord[2].xy + 0.025*dudv).rgb*2.0 - 1.0;
] [ 
    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0);
    gl_FragColor.rgb = mix(reflect, refract, invfresnel*0.5+0.5);
]
fastshader waterfade waterfadefast 2
altshader waterfade waterrefract

watershader "waterenv" 1 0 [
    vec3 bump = texture2D(tex1, gl_TexCoord[2].xy + 0.025*dudv).rgb*2.0 - 1.0;
    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0); 
    vec3 reflect = textureCube(tex0, camvec - 2.0*invfresnel*bump).rgb;
] [
    gl_FragColor.rgb = mix(reflect, gl_Color.rgb*depth.x, invfresnel*0.5+0.5) + spec*light;
    gl_FragColor.a = invfresnel*depth.y; 
]
watershader "waterenvfast" 0 0 [
    vec3 bump = texture2D(tex1, gl_TexCoord[2].xy + 0.025*dudv).rgb*2.0 - 1.0;
    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0); 
    vec3 reflect = textureCube(tex0, camvec - 2.0*invfresnel*bump).rgb;
] [
    gl_FragColor.rgb = mix(reflect, gl_Color.rgb*depth.x, invfresnel*0.5+0.5);
    gl_FragColor.a = invfresnel*depth.y; 
]
fastshader waterenv waterenvfast 2
altshader waterenv waterenvfast

watershader "waterenvrefract" 1 1 [
    vec2 dtc = gl_TexCoord[2].xy + 0.025*dudv;
    vec3 bump = texture2D(tex1, dtc).rgb*2.0 - 1.0;
    dudv = texture2D(tex2, dtc).xy*2.0 - 1.0;

    vec3 refract = texture2D(tex3, gl_TexCoord[0].xy/gl_TexCoord[0].w + 0.01*dudv).rgb;
    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0); 
    vec3 reflect = textureCube(tex0, camvec - 2.0*invfresnel*bump).rgb;
] [
    gl_FragColor = vec4(mix(reflect, refract, invfresnel*0.5+0.5) + spec*light, 0.0);
]
watershader "waterenvrefractfast" 0 1 [
    vec3 refract = texture2DProj(tex3, gl_TexCoord[0] + vec4(0.4*dudv, 0.0, 0.0)).rgb;
    vec3 bump = texture2D(tex1, gl_TexCoord[2].xy + 0.025*dudv).rgb*2.0 - 1.0;
    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0); 
    vec3 reflect = textureCube(tex0, camvec - 2.0*invfresnel*bump).rgb;
] [
    gl_FragColor = vec4(mix(reflect, refract, invfresnel*0.5+0.5), 0.0);
]
fastshader waterenvrefract waterenvrefractfast 2
altshader waterenvrefract waterenvrefractfast

watershader "waterenvfade" 1 1 [
    vec2 dtc = gl_TexCoord[2].xy + 0.025*dudv;
    vec3 bump = texture2D(tex1, dtc).rgb*2.0 - 1.0;
    dudv = texture2D(tex2, dtc).xy*2.0 - 1.0;

    vec2 projtc = gl_TexCoord[0].xy/gl_TexCoord[0].w;
    vec3 refract = texture2D(tex3, projtc + 0.01*dudv).rgb;
    float fade = gl_TexCoord[0].z + 4.0*texture2D(tex3, projtc).a;
    gl_FragColor.a = fade * clamp(gl_FragCoord.z, 0.0, 1.0);

    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0); 
    vec3 reflect = textureCube(tex0, camvec - 2.0*invfresnel*bump).rgb;
] [
    gl_FragColor.rgb = mix(reflect, refract, invfresnel*0.5+0.5) + spec*light;
]
watershader "waterenvfadefast" 0 1 [
    vec3 refract = texture2DProj(tex3, gl_TexCoord[0] + vec4(0.4*dudv, 0.0, 0.0)).rgb;
    gl_FragColor.a = gl_TexCoord[0].z + 4.0*texture2DProj(tex3, gl_TexCoord[0]).a;
    vec3 bump = texture2D(tex1, gl_TexCoord[2].xy + 0.025*dudv).rgb*2.0 - 1.0;
    float invfresnel = clamp(dot(camvec, bump), 0.0, 1.0); 
    vec3 reflect = textureCube(tex0, camvec - 2.0*invfresnel*bump).rgb;
] [
    gl_FragColor.rgb = mix(reflect, refract, invfresnel*0.5+0.5);
]
fastshader waterenvfade waterenvfadefast 2
altshader waterenvfade waterenvrefract

causticshader = [
    lazyshader 4 $arg1 [
        #pragma CUBE2_fog
        uniform vec4 texgenS, texgenT;
        void main(void)
        {
            gl_Position = ftransform();
            gl_TexCoord[0].xy = vec2(dot(texgenS.xyz, gl_Vertex.xyz), dot(texgenT.xyz, gl_Vertex.xyz)); 
        }
    ] [
        uniform vec4 frameoffset;
        uniform sampler2D tex0, tex1;
        void main(void)
        {
            @arg2
        }
    ]
]
causticshader caustic [
    gl_FragColor = frameoffset.x*texture2D(tex0, gl_TexCoord[0].xy) + frameoffset.y*texture2D(tex1, gl_TexCoord[0].xy);
]
causticshader causticfast [
    gl_FragColor = frameoffset.z*texture2D(tex0, gl_TexCoord[0].xy);
]
fastshader caustic causticfast 2

lazyshader 4 "lava" [
    #pragma CUBE2_fog
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
    }
] [
    uniform sampler2D tex0;
    void main(void)
    {
        gl_FragColor = gl_Color * texture2D(tex0, gl_TexCoord[0].xy) * 2.0; 
    }
]

lazyshader 4 "lavaglare" [
    #pragma CUBE2_fog
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color*2.0 - 1.0;
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
    }
] [
    uniform sampler2D tex0;
    void main(void)
    {
        vec4 glow = texture2D(tex0, gl_TexCoord[0].xy) * gl_Color;
        float k = max(glow.r, max(glow.g, glow.b));
        gl_FragColor = glow*k*k*32.0;
    }
]

lazyshader 4 "waterfallrefract" [
    #pragma CUBE2_fog
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
        gl_TexCoord[1] = gl_TextureMatrix[0] * gl_Vertex; 
    }
] [
    uniform vec4 dudvoffset;
    uniform sampler2D tex0, tex2, tex4;
    void main(void)
    {
        vec4 diffuse = texture2D(tex0, gl_TexCoord[0].xy);
        vec2 dudv = texture2D(tex2, gl_TexCoord[0].xy + 0.2*diffuse.xy + dudvoffset.xy).xy; 
        vec4 refract = texture2DProj(tex4, gl_TexCoord[1] + vec4(4.0*dudv, 0.0, 0.0));
        gl_FragColor = mix(refract, gl_Color, diffuse);
    }
]

lazyshader 4 "waterfallenvrefract" [
    #pragma CUBE2_fog
    uniform vec4 camera;
    varying vec3 camdir;
    varying mat3 world; 
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
        gl_TexCoord[1] = gl_TextureMatrix[0] * gl_Vertex;
        camdir = camera.xyz - gl_Vertex.xyz;
        vec3 absnorm = abs(gl_Normal);
        world = mat3(absnorm.yzx, -absnorm.zxy, gl_Normal);
    }
] [
    uniform vec4 dudvoffset;
    uniform sampler2D tex0, tex1, tex2, tex4;
    uniform samplerCube tex3;
    varying vec3 camdir;
    varying mat3 world; 
    void main(void)
    {
        vec4 diffuse = texture2D(tex0, gl_TexCoord[0].xy);
        vec2 dudv = texture2D(tex2, gl_TexCoord[0].xy + 0.2*diffuse.xy + dudvoffset.xy).xy; 
        vec3 normal = world * (texture2D(tex1, gl_TexCoord[0].xy + 0.1*dudv).rgb*2.0 - 1.0);
        vec4 refract = texture2DProj(tex4, gl_TexCoord[1] + vec4(4.0*dudv, 0.0, 0.0));
        vec3 camvec = normalize(camdir);
        float invfresnel = dot(normal, camvec);
        vec4 reflect = textureCube(tex3, 2.0*invfresnel*normal - camvec);
        gl_FragColor = mix(mix(reflect, refract, 1.0 - 0.4*step(0.0, invfresnel)), gl_Color, diffuse); 
    }
]
altshader waterfallenvrefract waterfallrefract

lazyshader 4 "waterfallenv" [
    #pragma CUBE2_fog
    uniform vec4 camera;
    varying vec3 camdir;
    varying mat3 world; 
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
        camdir = camera.xyz - gl_Vertex.xyz;
        vec3 absnorm = abs(gl_Normal);
        world = mat3(absnorm.yzx, -absnorm.zxy, gl_Normal);
    }
] [
    uniform vec4 dudvoffset;
    uniform sampler2D tex0, tex1, tex2;
    uniform samplerCube tex3;
    varying vec3 camdir;
    varying mat3 world; 
    void main(void)
    {
        vec4 diffuse = texture2D(tex0, gl_TexCoord[0].xy);
        vec2 dudv = texture2D(tex2, gl_TexCoord[0].xy + 0.2*diffuse.xy + dudvoffset.xy).xy; 
        vec3 normal = world * (texture2D(tex1, gl_TexCoord[0].xy + 0.1*dudv).rgb*2.0 - 1.0);
        vec3 camvec = normalize(camdir);
        vec4 reflect = textureCube(tex3, 2.0*dot(normal, camvec)*normal - camvec);
        gl_FragColor.rgb = mix(reflect.rgb, gl_Color.rgb, diffuse.rgb);
        gl_FragColor.a = 0.25 + 0.75*diffuse.r;    
    }
]

lazyshader 4 "glass" [
    uniform vec4 camera;
    varying vec3 rvec, camdir, normal;
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
        rvec = gl_MultiTexCoord0.xyz;
        camdir = camera.xyz - gl_Vertex.xyz;
        normal = gl_Normal;
    }
] [ 
    #pragma CUBE2_fogrgba vec4(0.0, 0.0, 0.0, 1.0)
    uniform samplerCube tex0;
    varying vec3 rvec, camdir, normal;
    void main(void)
    {
        vec3 camvec = normalize(camdir);
        vec3 reflect = textureCube(tex0, rvec).rgb;
   
        float invfresnel = max(dot(camvec, normal), 0.70); 
        gl_FragColor.rgb = mix(reflect, gl_Color.rgb*0.05, invfresnel);
        gl_FragColor.a = invfresnel * 0.95;
    }
]
lazyshader 4 "glassfast" [
    varying vec3 rvec;
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
        rvec = gl_MultiTexCoord0.xyz;
    }
] [ 
    #pragma CUBE2_fogrgba vec4(0.0, 0.0, 0.0, 1.0)
    uniform samplerCube tex0;
    varying vec3 rvec;
    void main(void)
    {
        vec3 reflect = textureCube(tex0, rvec).rgb;
        const float invfresnel = 0.75;
        gl_FragColor.rgb = mix(reflect, gl_Color.rgb*0.05, invfresnel);
        gl_FragColor.a = invfresnel * 0.95; 
    }
]
fastshader glass glassfast 2
altshader glass glassfast

lazyshader 4 "grass" [
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
        gl_TexCoord[1].xy = gl_MultiTexCoord1.xy;
    }
] [
    #pragma CUBE2_fogrgba vec4(0.0, 0.0, 0.0, 0.0)
    uniform sampler2D tex0, tex1;
    void main(void)
    {
        vec4 diffuse = texture2D(tex0, gl_TexCoord[0].xy);
        diffuse.rgb *= 2.0;
        vec4 lm = texture2D(tex1, gl_TexCoord[1].xy) * gl_Color;
        lm.rgb *= lm.a;
        gl_FragColor = diffuse * lm;
    }
]

shader 4 "overbrightdecal" [
    #pragma CUBE2_fog
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
    }
] [
    uniform sampler2D tex0;
    void main(void)
    {
        vec4 diffuse = texture2D(tex0, gl_TexCoord[0].xy);
        gl_FragColor = mix(gl_Color, diffuse, gl_Color.a);
    }
]

shader 4 "saturatedecal" [
    #pragma CUBE2_fog
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
    }
] [
    uniform sampler2D tex0;
    void main(void)
    {
        vec4 diffuse = texture2D(tex0, gl_TexCoord[0].xy);
        diffuse.rgb *= 2.0;
        gl_FragColor = diffuse * gl_Color;
    }
]

shader 4 "skyboxglare" [
    void main(void)
    {
        gl_Position = ftransform();
        gl_FrontColor = gl_Color;
        gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
    }
] [
    uniform sampler2D tex0;
    void main(void)
    {
        vec4 glare = texture2D(tex0, gl_TexCoord[0].xy) * gl_Color;
        gl_FragColor.rgb = vec3(dot(glare.rgb, vec3(10.56, 10.88, 10.56)) - 30.4);
        gl_FragColor.a = glare.a;
    }
]

