// shadow map filters, arg1 enables color sampling smfiltercolor = [result [ #define filtercolorshadow(tex, tc) texture2DRect(tex, tc.xy @(if $numargs [result [* @arg1]])).rgb ]] smfilterg5 = [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); vec2 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)); } @(if $arg1 [smfiltercolor 0.5]) ]] smfilterg3 = [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); vec2 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)); } @(if $arg1 [smfiltercolor 0.5]) ]] smfilterb5 = [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); } @(if $arg1 [smfiltercolor 0.5]) ]] smfilterb3 = [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))); } @(if $arg1 [smfiltercolor 0.5]) ]] smfilterrg = [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))); } @(if $arg1 [smfiltercolor 0.5]) ]] smfilternone = [result [ float filtershadow(vec3 shadowtc) { return float(shadow2DRect(tex4, shadowtc)); } @(if $arg1 [smfiltercolor]) ]] lazyshader 0 "smalphaclear" [ attribute vec4 vvertex; uniform vec2 shadowatlasscale; void main(void) { gl_Position = vec4(vvertex.xy * shadowatlasscale * 2.0 - 1.0, 0.0, 1.0); } ] [ fragdata(0) vec4 fragcolor; void main(void) { fragcolor = vec4(1.0); } ] loop i 2 [ lazyshader 0 (? $i "smalphablur2d" "smalphablurrect") [ attribute vec4 vvertex; attribute vec4 vtexcoord0; uniform vec2 shadowatlasscale; flat varying vec4 smbounds; varying vec4 texcoord0; void main(void) { gl_Position = vec4(vvertex.xy * shadowatlasscale * 2.0 - 1.0, 0.0, 1.0); smbounds = (vtexcoord0 + vec4(0.5, 0.5, -0.5, -0.5)) @(? $i [* shadowatlasscale.xyxy]); texcoord0 = (vvertex.xyxy + vec4(-1.0, -1.0, 1.0, 1.0)) @(? $i [* shadowatlasscale.xyxy]); } ] [ @(? $i [ uniform sampler2D tex0; #define texval(tc) texture2D(tex0, tc) ] [ uniform sampler2DRect tex0; #define texval(tc) texture2DRect(tex0, tc) ]) flat varying vec4 smbounds; varying vec4 texcoord0; fragdata(0) vec4 fragcolor; void main(void) { vec4 tc = vec4(max(texcoord0.xy, smbounds.xy), min(texcoord0.zw, smbounds.zw)); fragcolor = 0.25 * (texval(tc.xy) + texval(tc.zy) + texval(tc.xw) + texval(tc.zw)); } ] ]