// Physically based lightness calculation // for a rectangular area light perpendicular to a // matte (Lambertian) ground plane, expanding up and down. // details: https://hyperknot.com/blog/area_lights_in_shaders/ float area_light_antideriv(vec2 uv, float i, float h, float t) { float lxh = length(vec2(uv.x, h)); return -i * uv.x * atan((t-uv.y)/lxh) / lxh; } float area_light(vec2 uv, float i, float h_bottom, float h_top, float t_start, float t_end) { // i - light's intensity // h_top and h_bottom - the light's top and bottom above the ground // t_start and t_end - the light's start and end on the y-axis float v = + area_light_antideriv(uv, i, h_top, t_end) + area_light_antideriv(uv, i, h_bottom, t_start) - area_light_antideriv(uv, i, h_bottom, t_end) - area_light_antideriv(uv, i, h_top, t_start); return max(0., v); } float lin_to_srgb ( float val ) { if( val < 0.0031308 ) return val * 12.92; else return 1.055 * pow(val,1.0/2.4) - 0.055; } void mainImage( out vec4 fragColor, in vec2 fragCoord ){ vec2 uv = ( fragCoord - .5*iResolution.xy ) / iResolution.y; uv *= 2.; float h_top = pow(sin(iTime/3.), 2.) * 0.1 + 0.001; float v = area_light(uv, 0.05, 0.0, h_top, -0.5, 0.5); v += area_light(uv, -0.5, 0.0, h_top, -0.5, 0.5); v = lin_to_srgb(v); fragColor=vec4(v); }