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

ginterpdepth = [
    result [
        uniform vec2 lineardepthscale;
        uniform vec3 gdepthpackparams;
        @arg1 float lineardepth;
    ]
]

ginterpvert = [
    if (|| $gdepthformat $arg1) [ginterpdepth out]
]
msaainterpvert = [ginterpvert $msaasamples]

ginterpfrag = [
    result [
        layout(location = 0) out vec4 gcolor;
        layout(location = 1) out vec4 gnormal;
        @(? $gdepthformat [
            layout(location = 2) out vec4 gdepth;
            layout(location = 3) out vec4 gglow;
        ] [
            layout(location = 2) out vec4 gglow;
        ])
        @(if (|| $gdepthformat $arg1) [ginterpdepth in])
    ]
]
msaainterpfrag = [ginterpfrag $msaasamples]

gdepthpackvert = [
    if (|| $gdepthformat $arg1) [result [
        lineardepth = dot(lineardepthscale, gl_Position.zw);
    ]]
]
msaapackvert = [gdepthpackvert $msaasamples]

gpackdepth = [
    result [
        vec3 @arg1 = @arg2 * gdepthpackparams;
        @arg1 = vec3(@arg1.x, fract(@arg1.yz));
        @arg1.xy -= @arg1.yz * (1.0/255.0);
    ]
]

ghashdepth = [
    if $arg3 [
        arg1 = [(@arg1 + 5.0*@arg3)]
    ]
    if $arg2 [result [
        @arg2*0.76 + mix(0.75, 0.25, @arg2)*fract(@arg1*mix(-1.0/192.0, -1.0/64.0, @arg2))
    ]] [result [
        0.75*fract(@arg1*(-1.0/192.0))
    ]]
]

gdepthpackfrag = [
    result [
        @(if (= $gdepthformat 1) [result [
            @(gpackdepth packdepth lineardepth)
            gdepth.rgb = packdepth;
            gdepth.a = @(? $arg2 $arg2 [0.0]);
        ]] [? (> $gdepthformat 1) [
            gdepth.r = lineardepth;
        ]])
        @(if $usepacknorm [result [
            gnormal.a = @(if $arg1 [ghashdepth lineardepth $arg2 $arg3] [? $arg2 $arg2 [0.0]]);
        ]])
    ]
]
msaapackfrag = [gdepthpackfrag $msaasamples $arg1 $arg2]

gspecpack = [
    result [
        gcolor.a = @(if $arg3 [result [@arg3 *]]) (@arg1 * 85.0/255.0 + 0.5/255.0) @(if $arg2 [result [+ @(if $arg3 [result [@arg4 *]]) 84.0/255.0*clamp(1.5 - 1.5/(1.0 + @arg2), 0.0, 1.0)]]); 
    ]
]

gnormpack = [
    if $usepacknorm [result [
        gnormal.rgb = @arg1 @(if $arg2 [result [* sqrt(0.25 + 0.5*(@arg2))]]) * 0.5 + 0.5;
    ]] [result [
        gnormal.rgb = @arg1*0.5 + 0.5;
        gnormal.a = @(if $arg2 [result [(@arg2)]] [result [1.0]]);
    ]]
]

gnormpackdef = [
    result [
        #ifdef @arg2
            @(gnormpack $arg1 $arg2)
        #else
            @(gnormpack $arg1)
        #endif
    ]
]

gglowpack = [
    result [
        @(if $arg1 [result [
            float colork = max(gcolor.r, max(gcolor.g, gcolor.b)), glowk = max(@arg1.r, max(@arg1.g, @arg1.b));
        ]])
        glowk /= glowk + colork + 1.0e-3;
        gcolor.rgb = @(if $arg1 [result [mix(gcolor.rgb, @arg1, glowk)]] [result [gcolor.rgb]]) * (1.0 - 2.0*glowk*(glowk - 1.0));
        #define @arg2 1.0-glowk
    ]
]

gdepthunpackparams = [
    result [
        uniform vec3 gdepthscale;
        uniform vec3 gdepthunpackparams;
    ]
]

gdepthunpack = [
    if $arg6 [
        if $arg7 [result [
            vec3 @[arg7] = @[arg2].rgb;
            float @[arg1] = dot(@[arg7], gdepthunpackparams); 
            @arg3
        ]] [result [
            float @[arg1] = dot(@[arg2].rgb, gdepthunpackparams); 
            @arg3
        ]]
    ] [if (|| $gdepthformat $arg5) [
        if (|| (> $gdepthformat 1) $arg5) [result [
            float @[arg1] = @[arg2].r;
            @arg3
        ]] [result [
            float @[arg1] = dot(@[arg2].rgb, gdepthunpackparams); 
            @arg3
        ]]
    ] [if (=s $arg4 []) [result [
        float @[arg1] = gdepthscale.x / (@[arg2].r*gdepthscale.y + gdepthscale.z);
    ]] [result [
        float @[arg1] = @[arg2].r;
        @arg4
    ]]]]
]

gdepthunpackortho = [
    result [
        float @[arg1] = @(if (= $gdepthformat 1) [result [dot(@[arg2].rgb, gdepthunpackparams)]] [result [@[arg2].r]]);
        @arg3
    ]
]

gfetchdefs = [
    gfetchprefix = (? $arg3 $arg3 "gfetch")
    if (? (>= $numargs 2) $arg2 $msaalight) [result [
        uniform sampler2DMS @(prettylist $arg1);
        #define @[gfetchprefix]sample 0
        #define @[gfetchprefix](sampler, coords) texelFetch(sampler, ivec2(coords), @[gfetchprefix]sample)
        #define @[gfetchprefix]offset(sampler, coords, offset) texelFetch(sampler, ivec2(coords) + offset, @[gfetchprefix]sample)
        #define @[gfetchprefix]proj(sampler, coords) texelFetch(sampler, ivec2(coords.xy / coords.z), @[gfetchprefix]sample)
        @(if (! $arg3) [gdepthunpackparams])
    ]] [result [
        uniform sampler2DRect @(prettylist $arg1);
        #define @[gfetchprefix](sampler, coords) textureRect(sampler, coords)
        #define @[gfetchprefix]offset(sampler, coords, offset) textureRectOffset(sampler, coords, offset)
        #define @[gfetchprefix]proj(sampler, coords) textureRectProj(sampler, coords)
        @(if (! $arg3) [gdepthunpackparams])
    ]]
]

screentexcoord = [
    result [
        uniform vec4 screentexcoord@arg1;
        #define vtexcoord@arg1 (vvertex.xy * screentexcoord@arg1.xy + screentexcoord@arg1.zw)
    ]
]


