1 2-- needed optimizations 3-- 4-- a. only stepframe / update once per frame (don't event-drive from other 5-- states, invalidate + preframe state is ok) 6-- b. synch / track the caster-set rather than rebuild 7-- c. occlusion-pass to filter non-visible 8-- d. use depth buffer? 9-- e. use shadow-map as lookup for each render-output? (awful to write) 10-- f. downscale + blur + upscale + discard full-opaque (or use alpha test) 11-- g. re-use deformed surfaces? (i.e. cloth-drag-window should cast shadow) 12-- h. alpha- only mode 13-- i. draw rt without background in shadow mode, just use rt as shadow map 14-- on composition and just ignore all the rest, but would need depth vals. 15-- j. memory consumption can be reduced with: 16-- https://github.com/mattdesl/lwjgl-basics/wiki/2D-Pixel-Perfect-Shadows 17-- g. just go nuts and go raytrace / gi / radiosity 18-- h. limit (a) to the rate of the output display, (pfp- mask needed in eh) 19-- 20 21-- sketch for dynamic shadows, 22-- 23-- for both versions we build a rendertarget with the shadow casters, 24-- 1. linearize active space 25-- 2. for each window, use the wnd.width/wnd.height if shadowcaster 26-- 3. draw into dst as opaque 27-- 4. hook to update on each animated frame with window animations 28-- 29-- one options is: 30-- raytrace / render into 1D texture based on a point light (cursor) 31-- 32-- other option is: 33-- gaussian blur step, draw as overlay and discard opaque 34-- 35 36-- we keep the shaders and support script separate from the other 37-- subsystems so that the effects are easier to develop, test and 38-- share outside a full durden setup 39-- 40 41local shadow_gaussian_h = [[ 42uniform sampler2D map_tu0; 43uniform float obj_opacity; 44uniform vec2 obj_output_sz; 45varying vec2 texco; 46 47float get_alpha(float s, float t, float ra) 48{ 49 vec4 cv = texture2D(map_tu0, vec2(s, t)); 50 return cv.a; //float(ra > cv.a); 51} 52 53void main() 54{ 55 float sum = .0; 56 float blurh = 1.0 / obj_output_sz.x; 57 float ra = texture2D(map_tu0, texco.st).a; 58 59 if (ra < 0.09) 60 discard; 61 62#ifdef PASS2 63 sum += get_alpha(texco.x - 4.0 * blurh, texco.y, ra) * 0.05; 64 sum += get_alpha(texco.x - 3.0 * blurh, texco.y, ra) * 0.09; 65 sum += get_alpha(texco.x - 2.0 * blurh, texco.y, ra) * 0.12; 66 sum += get_alpha(texco.x - 1.0 * blurh, texco.y, ra) * 0.15; 67 sum += get_alpha(texco.x - 0.0 * blurh, texco.y, ra) * 0.16; 68 sum += get_alpha(texco.x + 1.0 * blurh, texco.y, ra) * 0.15; 69 sum += get_alpha(texco.x + 2.0 * blurh, texco.y, ra) * 0.12; 70 sum += get_alpha(texco.x + 3.0 * blurh, texco.y, ra) * 0.09; 71 sum += get_alpha(texco.x + 4.0 * blurh, texco.y, ra) * 0.05; 72#else 73 sum += get_alpha(texco.x, texco.y - 4.0 * blurh, ra) * 0.05; 74 sum += get_alpha(texco.x, texco.y - 3.0 * blurh, ra) * 0.09; 75 sum += get_alpha(texco.x, texco.y - 2.0 * blurh, ra) * 0.12; 76 sum += get_alpha(texco.x, texco.y - 1.0 * blurh, ra) * 0.15; 77 sum += get_alpha(texco.x, texco.y - 0.0 * blurh, ra) * 0.16; 78 sum += get_alpha(texco.x, texco.y + 1.0 * blurh, ra) * 0.15; 79 sum += get_alpha(texco.x, texco.y + 2.0 * blurh, ra) * 0.12; 80 sum += get_alpha(texco.x, texco.y + 3.0 * blurh, ra) * 0.09; 81 sum += get_alpha(texco.x, texco.y + 4.0 * blurh, ra) * 0.05; 82#endif 83 84 float a = float(sum > 1.0); 85 gl_FragColor = vec4(sum, sum, sum, 1.0); // 1.0 * a); // sum > 1.0); 86} 87]]; 88 89local shid = build_shader(nil, shadow_gaussian_h, "sgh"); 90 91local function tiler_casters(tiler, fx, fy) 92 local lst = {}; 93 94-- bin shadow caster order, encode into alpha channel (tradeoff in number 95-- of shadow caster levels) and then use the alpha value in the shader when 96-- doing the blur sampling 97 for j,k in ipairs(tiler.windows) do 98 local props = image_surface_resolve(k.border); 99 local nsrf = color_surface(props.width*fx, props.height*fy, 255, 255, 255); 100 101 if (not valid_vid(nsrf)) then 102 return; 103 else 104 show_image(nsrf); 105 move_image(nsrf, props.x * fx, props.y * fy); 106 blend_image(nsrf, 0.1 + props.order / 100); 107 order_image(nsrf, props.order); 108 force_image_blend(nsrf, BLEND_FORCE); 109 table.insert(lst, nsrf); 110 end 111 end 112 113-- other shadow casters can be added here, e.g. statusbar 114 return lst; 115end 116 117local function build_map(w, h) 118 local surf = alloc_surface(0.3 * w, 0.3 * h); 119 120 define_rendertarget( 121 surf, tiler_casters(active_display(), 0.4, 0.4), 122 RENDERTARGET_DETACH, RENDERTARGET_NOSCALE, 0, 123 bit.bor(RENDERTARGET_COLOR, RENDERTARGET_ALPHA)); 124 image_color(surf, 0, 0, 0, 0); 125 order_image(surf, 1000); 126 blend_image(surf, 1.0); 127 resize_image(surf, w, h); 128 rendertarget_forceupdate(surf); 129 image_shader(surf, shid); 130 return surf; 131end 132 133return function() 134 return build_map(active_display().width, active_display().height); 135end 136