//////////////////////////////////////////////// // // deferred shading // //////////////////////////////////////////////// msaadetectedges = [ result [{ @(if (glext "GL_EXT_shader_samples_identical") [result [ if(textureSamplesIdenticalEXT(tex1, ivec2(gl_FragCoord.xy))) { @arg1 } else ]]) { vec4 e = texelFetch(tex1, ivec2(gl_FragCoord.xy), 0); e.xyz -= 0.5; float maxdiff = 0.98*0.98*dot(e.xyz, e.xyz); @(loopconcat+ i 1 (- $msaasamples 1) [result [ vec4 e@i = texelFetch(tex1, ivec2(gl_FragCoord.xy), @i); e@i.xyz -= 0.5; if(abs(e.w-e@i.w) <= 2.0/255.0 && pow(dot(e@i.xyz, e.xyz), 2.0) >= maxdiff*dot(e@i.xyz, e@i.xyz)) { ]]) @arg1 @(loopconcat+ i 1 (- $msaasamples 1) [result [ } ]]) } }] ] lazyshader 0 msaaedgedetect [ attribute vec4 vvertex; void main(void) { gl_Position = vvertex; } ] [ @(? (glext "GL_EXT_shader_samples_identical") [ #extension GL_EXT_shader_samples_identical : enable ]) uniform sampler2DMS tex1; void main(void) { @(msaadetectedges [discard;]) } ] // deferredlighttype: // p -> point-light shadow (default cubemap) // c -> CSM // a -> AO // A -> AO sun // r -> radiance hints // G -> 5x5 weighted gather filter // g -> 3x3 weighted gather filter // E -> 5x5 weighted bilinear filter // F -> 3x3 weighted bilinear filter // f -> 4x rotated grid filter // m -> minimap // M -> multisampled // O -> sample 1 // R -> manual resolve // S -> sample shading // T -> edge detection // n -> tile batching // s -> spotlights // t -> transparent // b -> combined base/light variants // d -> avatar shadow dist bias variants // D -> disable dist bias // z -> spec toggle dlopt = [ >= (strstr $deferredlighttype $arg1) 0 ] unpacknormbias = 0.005 unpacknormscale = (+f 1 (*f 2 $unpacknormbias)) unpacknorm = [ result [ @arg1 = clamp(@arg1 * @(divf $unpacknormscale 0.5) - @(+f (*f $unpacknormscale (divf 0.25 0.5)) $unpacknormbias), 0.0, 1.0); ] ] unpackspec = [ result [ vec3 camdir = normalize(camera - pos.xyz); float facing = 2.0*dot(normal.xyz, camdir); float specscale = min(3.0*(diffuse.a + 0.5/255.0), 2.999), gloss = floor(specscale); specscale -= gloss; specscale = (0.35 + 0.15*gloss) * specscale / (1.5 - specscale); gloss = 5.0 + 17.0*gloss; ] ] unpackdistbias = [ cond [$avatar] [result [ #define distbias -@avatarshadowbias ]] [|| $transparent [dlopt "d"] [dlopt "D"] [dlopt "m"]] [result [ #define distbias 0.0 ]] [result [ float distbias = -@avatarshadowbias * @(? (dlopt "a") [avatarmask] [step(fogcoord, @avatarshadowdist) * @(? $msaasamples [step(0.75, normal.a)] [normal.a])]); ]] ] deferredlightvariantshader = [ local deferredlighttype deferredlighttype = $arg3 numsplits = (+ $arg4 0) numrh = (+ $arg5 0) numlights = (+ $arg6 0) baselight = (< (mod $arg2 4) 2) spotlight = (>= (mod $arg2 8) 4) transparent = (<= 8 $arg2 16) avatar = (<= 17 $arg2 31) variantshader 0 $arg1 $arg2 (? (< $arg2 0) [ attribute vec4 vvertex; uniform mat4 lightmatrix; void main(void) { gl_Position = lightmatrix * vvertex; } ]) [ @(? (&& (dlopt "S") [< $glslversion 400]) [ #extension GL_ARB_sample_shading : enable ]) @(? (&& (dlopt "T") [glext "GL_EXT_shader_samples_identical"]) [ #extension GL_EXT_shader_samples_identical : enable ]) @(if (dlopt "M") [result [ uniform sampler2DMS tex0, tex1, tex3 @(? $transparent [, tex2]); ]] [result [ uniform sampler2DRect tex0, tex1, tex3 @(? $transparent [, tex2]); ]]) @(if (|| (dlopt "p") (dlopt "c")) [ if (|| (dlopt "g") (dlopt "G")) [if (> $usetexgather 1) [result [ uniform sampler2DShadow tex4; ]] [result [ uniform sampler2D tex4; ]]] [result [ uniform sampler2DRectShadow tex4; ]] ]) @(if $numlights [result [ uniform vec4 lightpos[@@numlights]; uniform vec4 lightcolor[@@numlights]; @(if $spotlight [result [ uniform vec4 spotparams[@@numlights]; ]]) @(if (dlopt "p") [result [ uniform vec4 shadowparams[@@numlights]; uniform vec2 shadowoffset[@@numlights]; ]]) ]]) @(if $numsplits [result [ uniform vec4 csmtc[@@numsplits]; uniform vec3 csmoffset[@@numsplits]; uniform vec2 csmz; ]]) @(if (dlopt "c") [result [ uniform mat3 csmmatrix; uniform vec3 sunlightdir; uniform vec3 sunlightcolor; @(if (dlopt "r") [result [ uniform vec3 skylightcolor; uniform float giscale, rhnudge, rhbounds; uniform vec4 rhtc[@@numrh]; uniform sampler3D tex6, tex7, tex8, tex9; ]]) ]]) uniform vec3 camera; uniform mat4 worldmatrix; uniform vec4 fogdir; uniform vec3 fogcolor; uniform vec2 fogdensity; uniform vec4 radialfogscale; uniform vec2 shadowatlasscale; uniform vec4 lightscale; @(? (&& (dlopt "a") [! $avatar] [! $transparent]) [uniform sampler2DRect tex5; uniform vec2 aoscale; uniform vec4 aoparams;]) @(gdepthunpackparams) fragdata(0) vec4 fragcolor; @(if (dlopt "p") [ ? $spotlight [ vec3 getspottc(vec3 dir, float spotdist, vec4 spotparams, vec4 shadowparams, vec2 shadowoffset, float distbias) { vec2 mparams = shadowparams.xy / max(spotdist + distbias, 1e-5); return vec3((dir.xy - spotparams.xy*(spotdist + (spotparams.z > 0.0 ? 1.0 : -1.0)*dir.z)*shadowparams.z) * mparams.x + shadowoffset, mparams.y + shadowparams.w); } ] [ vec3 getshadowtc(vec3 dir, vec4 shadowparams, vec2 shadowoffset, float distbias) { vec3 adir = abs(dir); float m = max(adir.x, adir.y), mz = max(adir.z, m); vec2 mparams = shadowparams.xy / max(mz + distbias, 1e-5); vec4 proj; if(adir.x > adir.y) proj = vec4(dir.zyx, 0.0); else proj = vec4(dir.xzy, 1.0); if(adir.z > m) proj = vec4(dir, 2.0); return vec3(proj.xy * mparams.x + vec2(proj.w, step(0.0, proj.z)) * shadowparams.z + shadowoffset, mparams.y + shadowparams.w); } ] ]) @(if (|| (dlopt "p") [dlopt "c"]) [ cond [dlopt "G"] [result [ @(? (> $usetexgather 1) [ #define shadowgather(center, xoff, yoff) textureGatherOffset(tex4, center, shadowtc.z, ivec2(xoff, yoff)) ] [ #define shadowgather(center, xoff, yoff) step(shadowtc.z, textureGatherOffset(tex4, center, ivec2(xoff, yoff))) ]) float filtershadow(vec3 shadowtc) { vec2 offset = fract(shadowtc.xy - 0.5), center = (shadowtc.xy - offset)*shadowatlasscale; vec4 group1 = shadowgather(center, -2, -2); vec4 group2 = shadowgather(center, 0, -2); vec4 group3 = shadowgather(center, 2, -2); vec4 group4 = shadowgather(center, -2, 0); vec4 group5 = shadowgather(center, 0, 0); vec4 group6 = shadowgather(center, 2, 0); vec4 group7 = shadowgather(center, -2, 2); vec4 group8 = shadowgather(center, 0, 2); vec4 group9 = shadowgather(center, 2, 2); vec4 locols = vec4(group1.ab, group3.ab); vec4 hicols = vec4(group7.rg, group9.rg); locols.yz += group2.ab; hicols.yz += group8.rg; vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) + vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) + mix(locols, hicols, offset.y); vec4 cols = group5 + vec4(group2.rg, group8.ab); cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x); return dot(cols, vec4(1.0/25.0)); } ]] [dlopt "g"] [result [ @(? (> $usetexgather 1) [ #define shadowgather(center, xoff, yoff) textureGatherOffset(tex4, center, shadowtc.z, ivec2(xoff, yoff)) ] [ #define shadowgather(center, xoff, yoff) step(shadowtc.z, textureGatherOffset(tex4, center, ivec2(xoff, yoff))) ]) float filtershadow(vec3 shadowtc) { vec2 offset = fract(shadowtc.xy - 0.5), center = (shadowtc.xy - offset)*shadowatlasscale; vec4 group1 = shadowgather(center, -1, -1); vec4 group2 = shadowgather(center, 1, -1); vec4 group3 = shadowgather(center, -1, 1); vec4 group4 = shadowgather(center, 1, 1); vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) + mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y); return dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0)); } ]] [dlopt "E"] [result [ #define shadowval(xy, xoff, yoff) float(shadow2DRect(tex4, vec3(xy + vec2(xoff, yoff), shadowtc.z))) float filtershadow(vec3 shadowtc) { vec2 offset = fract(shadowtc.xy - 0.5); vec4 center = vec4(shadowtc.xy - offset + 0.5, shadowtc.xy - offset*0.5); vec4 size = vec4(offset + 1.0, 2.0 - offset); return (1.0/25.0)*dot(size.zxzx*size.wwyy, vec4(shadowval(center.zw, -1.5, -1.5), shadowval(center.zw, 2.0, -1.5), shadowval(center.zw, -1.5, 2.0), shadowval(center.zw, 2.0, 2.0))) + (2.0/25.0)*dot(size, vec4(shadowval(center.zy, 2.0, 0.0), shadowval(center.xw, 0.0, 2.0), shadowval(center.zy, -1.5, 0.0), shadowval(center.xw, 0.0, -1.5))) + (4.0/25.0)*shadowval(center.xy, 0.0, 0.0); } ]] [dlopt "F"] [result [ #define shadowval(center, xoff, yoff) float(shadow2DRect(tex4, center + vec3(xoff, yoff, 0.0))) float filtershadow(vec3 shadowtc) { vec2 offset = fract(shadowtc.xy - 0.5); vec3 center = shadowtc; //center.xy -= offset; //vec4 size = vec4(offset + 1.0, 2.0 - offset), weight = vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0); //return (1.0/9.0)*dot(size.zxzx*size.wwyy, // vec4(shadowval(center, weight.zw), // shadowval(center, weight.xw), // shadowval(center, weight.zy), // shadowval(center, weight.xy))); center.xy -= offset*0.5; vec4 size = vec4(offset + 1.0, 2.0 - offset); return (1.0/9.0)*dot(size.zxzx*size.wwyy, vec4(shadowval(center, -0.5, -0.5), shadowval(center, 1.0, -0.5), shadowval(center, -0.5, 1.0), shadowval(center, 1.0, 1.0))); } ]] [dlopt "f"] [result [ #define shadowval(center, xoff, yoff) float(shadow2DRect(tex4, center + vec3(xoff, yoff, 0.0))) float filtershadow(vec3 shadowtc) { return dot(vec4(0.25), vec4(shadowval(shadowtc, -0.4, 1.0), shadowval(shadowtc, -1.0, -0.4), shadowval(shadowtc, 0.4, -1.0), shadowval(shadowtc, 1.0, 0.4))); } ]] [result [ #define filtershadow(shadowtc) float(shadow2DRect(tex4, shadowtc)) ]] ]) @(if (dlopt "c") [result [ vec3 getcsmtc(vec3 pos, float distbias) { vec3 tc, offset; pos = csmmatrix * pos; pos.z -= distbias; tc.z = csmz.x + pos.z*csmz.y; @(loopconcat j $numsplits [result [ tc.xy = csmtc[@@j].xy + pos.xy*csmtc[@@j].z; offset = csmoffset[@@j]; if(max(abs(tc.x), abs(tc.y)) >= csmtc[@@j].w) { ]]) offset = vec3(-16384.0); @(loopconcat j $numsplits [result [ } ]]) return tc + offset; } @(if (dlopt "r") [result [ vec4 getrhlight(vec3 pos, vec3 norm) { vec3 tc; float offset; pos += norm*rhnudge; @(loopconcat j $numrh [result [ tc = rhtc[@@j].xyz + pos*rhtc[@@j].w; offset = @(divf (+f 0.5 $j) $numrh); if(max(max(abs(tc.x), abs(tc.y)), abs(tc.z)) >= rhbounds) { ]]) tc = vec3(4.0); @(loopconcat j $numrh [result [ } ]]) tc.xy += 0.5; tc.z = tc.z * @(divf 1 $numrh) + offset; vec4 shr = texture3D(tex6, tc), shg = texture3D(tex7, tc), shb = texture3D(tex8, tc), sha = texture3D(tex9, tc); shr.rgb -= 0.5; shg.rgb -= 0.5; shb.rgb -= 0.5; sha.rgb -= 0.5; vec4 basis = vec4(norm*-(1.023326*0.488603/3.14159*2.0), (0.886226*0.282095/3.14159)); return clamp(vec4(dot(basis, shr), dot(basis, shg), dot(basis, shb), min(dot(basis, sha), norm.z + 1.0)), 0.0, 1.0); } ]]) ]]) void main(void) { @(if (dlopt "M") [ if (dlopt "R") [result [ @(if (dlopt "T") [result [ bool shouldresolve = true; @(msaadetectedges [shouldresolve = false;]) ]]) #define gfetch(sampler, coords) texelFetch(sampler, ivec2(coords), sampleidx) vec4 resolved = vec4(0.0); #define accumlight(light) resolved.rgb += light #define accumalpha(alpha) resolved.a += alpha @(if (&& [dlopt "a"] [! $avatar] [! $transparent]) [result [ float ao = texture2DRect(tex5, gl_FragCoord.xy*aoscale).r; ]]) for(int sampleidx = 0; sampleidx < @msaasamples; sampleidx++) { ]] [result [ @(if (dlopt "T") [msaadetectedges [discard;]]) #define gfetch(sampler, coords) texelFetch(sampler, ivec2(coords), @(? (dlopt "S") [gl_SampleID] (? (dlopt "O") 1 0))) #define accumlight(light) fragcolor.rgb = light #define accumalpha(alpha) fragcolor.a = alpha ]] ] [result [ #define gfetch(sampler, coords) texture2DRect(sampler, coords) #define accumlight(light) fragcolor.rgb = light #define accumalpha(alpha) fragcolor.a = alpha ]]) @(if (|| $baselight [> $numlights 1]) [result [ vec4 normal = gfetch(tex1, gl_FragCoord.xy); @(if $transparent [result [ @(? (! $ghasstencil) [ if(normal.x + normal.y == 0.0) discard; ]) normal.xyz = normal.xyz*2.0 - 1.0; @(if $usepacknorm [result [ float alpha = dot(normal.xyz, normal.xyz); normal.xyz *= inversesqrt(alpha); @(if $baselight [unpacknorm alpha]) ]] [result [ #define alpha normal.a ]]) vec4 diffuse = gfetch(tex0, gl_FragCoord.xy); @(? $baselight [ vec3 glow = gfetch(tex2, gl_FragCoord.xy).rgb; ]) ]] [result [ @(? $baselight [ float alpha = float(normal.x + normal.y != 0.0); ] [ #define alpha 1.0 ]) normal.xyz = normal.xyz*2.0 - 1.0; @(if $usepacknorm [result [ float glowscale = dot(normal.xyz, normal.xyz); normal.xyz *= inversesqrt(glowscale); @(unpacknorm glowscale) ]] [result [ #define glowscale normal.a ]]) vec4 diffuse = gfetch(tex0, gl_FragCoord.xy); @(? $baselight [ vec3 glow = diffuse.rgb * (1.0 - glowscale); ]) diffuse.rgb *= glowscale; ]]) ]]) @(if (dlopt "m") [if (+ $numlights (dlopt "c")) [ gdepthunpackortho depth [gfetch(tex3, gl_FragCoord.xy)] [ vec3 pos = (worldmatrix * vec4(gl_FragCoord.xy, depth, 1.0)).xyz; ] ]] [if (+ $numlights (dlopt "c")) [result [ @(gdepthunpack depth [gfetch(tex3, gl_FragCoord.xy)] [ vec3 pos = (worldmatrix * vec4(depth*gl_FragCoord.xy, depth, 1.0)).xyz; ] [ vec4 pos = worldmatrix * vec4(gl_FragCoord.xy, depth, 1.0); pos.xyz /= pos.w; ]) @(? (|| $baselight [> $numlights 1]) [ float fogcoord = length(camera - pos.xyz); ]) @(if (> (+ $numlights (dlopt "c")) 1) [unpackspec]) ]] [result [ @(gdepthunpack depth [gfetch(tex3, gl_FragCoord.xy)]) @(? $baselight [ float fogcoord = -depth*length(vec3(gl_FragCoord.xy*radialfogscale.xy + radialfogscale.zw, 1.0)); ]) ]]]) @(if $baselight [result [ vec3 light = lightscale.rgb; @(? (dlopt "r") [ vec4 rhlight = getrhlight(pos.xyz, normal.xyz); light += rhlight.a * skylightcolor; ]) light *= diffuse.rgb; @(if (&& (dlopt "a") [! $avatar] [! $transparent]) [result [ @(? (! (&& (dlopt "M") [dlopt "R"])) [ float ao = texture2DRect(tex5, gl_FragCoord.xy*aoscale).r; ]) @(if (dlopt "d") [result [ #define aomask ao ]] [result [ float avatarmask = step(fogcoord, @avatarshadowdist) * @(? $msaasamples [step(0.75, normal.a)] [normal.a]); float aomask = clamp(ao + avatarmask, 0.0, 1.0); ]]) light *= aoparams.x + aomask*aoparams.y; ]]) light += glow * lightscale.a; ]] [result [ vec3 light = vec3(0.0); ]]) @(if (> (+ (? (dlopt "p") $numlights) (dlopt "c")) 1) [unpackdistbias]) @(if (dlopt "c") [result [ @(? (dlopt "r") [ vec3 sunlight = rhlight.rgb * giscale * diffuse.rgb; ]) float sunfacing = dot(sunlightdir, normal.xyz); if(sunfacing > 0.0) { @(if (= (+ (? (dlopt "p") $numlights) (dlopt "c")) 1) [unpackdistbias]) vec3 csmtc = getcsmtc(pos.xyz, distbias); float sunoccluded = filtershadow(csmtc); @(if (dlopt "m") [result [ light += diffuse.rgb*sunfacing * sunlightcolor * sunoccluded; ]] [result [ @(if (= (+ $numlights (dlopt "c")) 1) [unpackspec]) float sunspec = pow(clamp(sunfacing*facing - dot(camdir, sunlightdir), 0.0, 1.0), gloss) * specscale; @(if (dlopt "r") [result [ sunlight += (diffuse.rgb*sunfacing + sunspec) * sunoccluded; ]] [result [ @(? (&& (dlopt "A") [! $avatar] [! $transparent]) [ sunoccluded *= aoparams.z + aomask*aoparams.w; ]) light += (diffuse.rgb*sunfacing + sunspec) * sunoccluded * sunlightcolor; ]]) ]]) } @(if (dlopt "r") [result [ @(? (&& (dlopt "A") [! $avatar] [! $transparent]) [ sunlight *= aoparams.z + aomask*aoparams.w; ]) light += sunlight * sunlightcolor; ]]) ]]) @(loopconcat j $numlights [result [ vec3 light@[j]dir = lightpos[@@j].xyz - pos.xyz * lightpos[@@j].w; float light@[j]dist2 = dot(light@[j]dir, light@[j]dir); if(light@[j]dist2 < 1.0) { @(if (= (+ $numlights $baselight) 1) [result [ vec4 normal = gfetch(tex1, gl_FragCoord.xy); @(? (&& $transparent [! $ghasstencil]) [ if(normal.x + normal.y == 0.0) discard; ]) normal.xyz = normal.xyz*2.0 - 1.0; @(? $usepacknorm [ float glowscale = dot(normal.xyz, normal.xyz); normal.xyz *= inversesqrt(glowscale); ] [ #define glowscale normal.a ]) ]]) float light@[j]facing = dot(light@[j]dir, normal.xyz); if(light@[j]facing > 0.0) { float light@[j]invdist = inversesqrt(light@[j]dist2); @(if $spotlight [result [ float spot@[j]dist = dot(light@[j]dir, spotparams[@@j].xyz); float spot@[j]atten = 1.0 - (1.0 - light@[j]invdist * spot@[j]dist) * spotparams[@@j].w; if(spot@[j]atten > 0.0) { ]]) float light@[j]atten = 1.0 - light@[j]dist2 * light@[j]invdist; @(? (&& (= (+ $numlights $baselight) 1) [! (dlopt "m")]) [ float fogcoord = length(camera - pos.xyz); ]) @(if (= (+ (? (dlopt "p") $numlights) (dlopt "c")) 1) [unpackdistbias]) @(if $spotlight [ if (dlopt "p") [result [ vec3 spot@[j]tc = getspottc(light@[j]dir, spot@[j]dist, spotparams[@@j], shadowparams[@@j], shadowoffset[@@j], distbias * lightpos[@@j].w); light@[j]atten *= spot@[j]atten * filtershadow(spot@[j]tc); ]] [result [ light@[j]atten *= spot@[j]atten; ]] ] [ if (dlopt "p") [result [ vec3 shadow@[j]tc = getshadowtc(light@[j]dir, shadowparams[@@j], shadowoffset[@@j], distbias * lightpos[@@j].w); light@[j]atten *= filtershadow(shadow@[j]tc); ]] ]) @(if (= (+ $numlights $baselight) 1) [result [ vec4 diffuse = gfetch(tex0, gl_FragCoord.xy); @(if (! $transparent) [result [ @(if $usepacknorm [unpacknorm glowscale]) diffuse.rgb *= glowscale; ]]) ]]) light@[j]facing *= light@[j]invdist; @(if (dlopt "m") [result [ light += diffuse.rgb*light@[j]facing * lightcolor[@@j].rgb * light@[j]atten; ]] [result [ @(if (= (+ $numlights (dlopt "c")) 1) [unpackspec]) float light@[j]spec = pow(clamp(light@[j]facing*facing - light@[j]invdist*dot(camdir, light@[j]dir), 0.0, 1.0), gloss) * specscale; @(if (dlopt "z") [result [ light@[j]spec *= lightcolor[@@j].a; ]]) light += (diffuse.rgb*light@[j]facing + light@[j]spec) * lightcolor[@@j].rgb * light@[j]atten; @(? (= (+ $numlights $baselight) 1) [ float foglerp = clamp(exp2(fogcoord*fogdensity.x)*fogdensity.y, 0.0, 1.0); light *= foglerp; ]) ]]) @(? $spotlight [}]) } } ]]) @(if (dlopt "m") [if $baselight [result [ accumlight(light); accumalpha(alpha); ]] [result [ accumlight(light); accumalpha(0.0); ]]] [if (|| $baselight [> $numlights 1]) [result [ float foglerp = clamp(exp2(fogcoord*fogdensity.x)*fogdensity.y, 0.0, 1.0); @(? $baselight [ accumlight(mix(fogcolor*alpha, light, foglerp)); accumalpha(alpha); ] [ accumlight(light*foglerp); accumalpha(0.0); ]) ]] [result [ accumlight(light); accumalpha(0.0); ]]]) @(if (dlopt "R") [result [ @(? (dlopt "T") [if(!shouldresolve) break;]) } @(? (dlopt "T") [if(shouldresolve)]) resolved *= @(divf 1 $msaasamples); fragcolor = resolved; ]]) } ] $arg7 ] deferredlightshader = [ deferredlighttype = (concatword $arg1 $arg2 $arg3) shadername = (concatword "deferredlight" $deferredlighttype) basevariants = (* (max $arg6 1) 2 (? (dlopt "b") 2 1) (? (dlopt "s") 2 1)) maxvariants = $basevariants if (dlopt "t") [maxvariants = (+ $maxvariants $basevariants 1)] if (dlopt "d") [maxvariants = (+ $maxvariants $basevariants 1)] deferredlightvariantshader $shadername -1 (concatword $arg1 $arg3) $arg4 $arg5 0 $maxvariants // base shader, no points lights, sunlight if (dlopt "t") [ deferredlightvariantshader $shadername 16 (concatword $arg1 $arg3) $arg4 $arg5 0 $maxvariants // row 16, trasparency, base shader, no points lights, sunlight ] if (dlopt "d") [ deferredlightvariantshader $shadername 17 (concatword $arg1 $arg3) $arg4 $arg5 0 $maxvariants // row 17, avatar, base shader, no points lights, sunlight ] loop+ i 1 (max $arg6 1) [ if (dlopt "b") [ deferredlightvariantshader $shadername 0 (concatword $arg1 $arg3) $arg4 $arg5 $i $maxvariants // row 0, point lights, sunlight deferredlightvariantshader $shadername 1 (concatword $arg1 $arg2 $arg3) $arg4 $arg5 $i $maxvariants // row 1, shadowed point lights, sunlight ] deferredlightvariantshader $shadername 2 $arg1 $arg4 $arg5 $i $maxvariants // row 2, point lights deferredlightvariantshader $shadername 3 (concatword $arg1 $arg2) $arg4 $arg5 $i $maxvariants // row 3, shadowed point lights if (dlopt "s") [ if (dlopt "b") [ deferredlightvariantshader $shadername 4 (concatword $arg1 $arg3) $arg4 $arg5 $i $maxvariants // row 4, spot lights, sunlight deferredlightvariantshader $shadername 5 (concatword $arg1 $arg2 $arg3) $arg4 $arg5 $i $maxvariants // row 5, shadowed spot lights, sunlight ] deferredlightvariantshader $shadername 6 $arg1 $arg4 $arg5 $i $maxvariants // row 6, spot lights deferredlightvariantshader $shadername 7 (concatword $arg1 $arg2) $arg4 $arg5 $i $maxvariants // row 7, shadowed spot lights ] if (dlopt "t") [ if (dlopt "b") [ deferredlightvariantshader $shadername 8 (concatword $arg1 $arg3) $arg4 $arg5 $i $maxvariants // row 8, transparent, point lights, sunlight deferredlightvariantshader $shadername 9 (concatword $arg1 $arg2 $arg3) $arg4 $arg5 $i $maxvariants // row 9, transparent, shadowed point lights, sunlight ] deferredlightvariantshader $shadername 10 $arg1 $arg4 $arg5 $i $maxvariants // row 10, transparent, point lights deferredlightvariantshader $shadername 11 (concatword $arg1 $arg2) $arg4 $arg5 $i $maxvariants // row 11, transparent, shadowed point lights if (dlopt "s") [ if (dlopt "b") [ deferredlightvariantshader $shadername 12 (concatword $arg1 $arg3) $arg4 $arg5 $i $maxvariants // row 12, transparent, spot lights, sunlight deferredlightvariantshader $shadername 13 (concatword $arg1 $arg2 $arg3) $arg4 $arg5 $i $maxvariants // row 13, transparent, shadowed spot lights, sunlight ] deferredlightvariantshader $shadername 14 $arg1 $arg4 $arg5 $i $maxvariants // row 14, transparent, spot lights deferredlightvariantshader $shadername 15 (concatword $arg1 $arg2) $arg4 $arg5 $i $maxvariants // row 15, transparent, shadowed spot lights ] ] if (dlopt "d") [ if (dlopt "b") [ deferredlightvariantshader $shadername 24 (concatword $arg1 $arg3) $arg4 $arg5 $i $maxvariants // row 24, avatar, point lights, sunlight deferredlightvariantshader $shadername 25 (concatword $arg1 $arg2 $arg3) $arg4 $arg5 $i $maxvariants // row 25, avatar, shadowed point lights, sunlight ] deferredlightvariantshader $shadername 26 $arg1 $arg4 $arg5 $i $maxvariants // row 26, avatar, point lights deferredlightvariantshader $shadername 27 (concatword $arg1 $arg2) $arg4 $arg5 $i $maxvariants // row 27, avatar, shadowed point lights if (dlopt "s") [ if (dlopt "b") [ deferredlightvariantshader $shadername 28 (concatword $arg1 $arg3) $arg4 $arg5 $i $maxvariants // row 28, avatar, spot lights, sunlight deferredlightvariantshader $shadername 29 (concatword $arg1 $arg2 $arg3) $arg4 $arg5 $i $maxvariants // row 29, avatar, shadowed spot lights, sunlight ] deferredlightvariantshader $shadername 30 $arg1 $arg4 $arg5 $i $maxvariants // row 30, avatar, spot lights deferredlightvariantshader $shadername 31 (concatword $arg1 $arg2) $arg4 $arg5 $i $maxvariants // row 31, avatar, shadowed spot lights ] ] ] ]