/*
[lightsdf] samples occlusion diagonally (root of unity?)
,to estimate non-point-light-emnmitters (like a pseudo-DFT?)
This fails for large curvature and convex emmitters
, but gives you some cheap decent RADiosity almost for free
, but still looks decent. (roudned corners of convex square emmitter)
, but it LOD-scales VERY nicely, can be VERY fast and look convincing (see in lowres)
Bayer matrix is used in favor of better (and more dynamic) performance;

my scaling of bayerMatrix*X/iResolution seems off (semi intentionally)
making the bayer matix exponentially lower res than screenspace resolution.
this way it keeps (inverse-)cubic performance on low res
, while getting exponentially better quality on higher res.
- this is mostly a lowres-preview opengl-crashing evasion.
- but also demoes how you could to a buas
-, by [DistanceToScreenCenter*DistanceToMouseCursor] of [ /XdXBzH ]

this shader does not rotate bayer matrixces, like [ /ltKcDt ] does.
- mostly because i tend to not trust complex transforms on bayer-hyperplane moire.
- but also because this shader samples rotated anyways.

this shader does not use any frame buffers
, which should easily get performance/quality a lot higher
, but also makes the shader a lot less compatible to bifferless canvases.
*/

//crepuscularity with bayer    (with RADiosity)
//self   (bayer,instead of hash)            : https://www.shadertoy.com/view/Xtcfzj

//crepuscularity without bayer (with RADiosity)
//parent (hash instead of bayer)            : https://www.shadertoy.com/view/lldcDf
//crepuscularity with 3dto2d differenceGrad : https://www.shadertoy.com/view/4lXBW2

//crepuscularity without bayer (no RADiosity? hard to tell.)
//dr2-noise with a bias for3d derivatives   : https://www.shadertoy.com/view/llXfRs
//in comparison to slow 3d (crashes opengl) : https://www.shadertoy.com/view/lltfRB
//
//crepuscularity with (no RADiosity)
//crepuscularity with highres Bayer         : https://www.shadertoy.com/view/4dyXWy
//crepuscularity with highres Bayer2        : https://www.shadertoy.com/view/ltsyWl
//crepuscularity with only 3 hyperplaneTaps : https://www.shadertoy.com/view/ltKcDt

//compare that to [bayer-toggled bokeh  (no radiosity, no crepuscularity):
//then you can define "quality" depentant on "eye focus"
//- "eye focus" is something like DistanceToScreenCenter*DistanceToMouseCursor
//- scale that gradient by a bayer matrix and use that as if(){} quality-bias
//- ,that toggles/mixes 4 Crepuscularity/Radiosity/bokeh-compositions, as in
//- https://www.shadertoy.com/view/XdXBzH
//this works best for "bokeh" as it implies correlated things;focus/peripheralVision
//,but it should work just as well to set bayer-quality for crepuscularity/radiosity

//2d zoom
#define ViewZoom 10.
//divide by/aa for hairline drawing and sharp smoothstep()
#define Aa (min(iResolution.x,iResolution.y)/ViewZoom)
#define fra(u)(u-.5*iResolution.xy)*ViewZoom/iResolution.y//usually first function of mainImage(),not typecast.


#define pi acos(-1.)//trig definition for 3.14...can be better for smarter compilers.
#define vec1 float
#define sat(x)clamp(x,0.,1.)
#define dd(a)dot(a,a)
#define u5(a)((a)*.5+.5)
#define u2(a)((a)*2.-1.)
#define ss(a,u)smoothstep(a,-a,u)
vec1 suv(vec4 a){return dot(vec4(1),a);}vec1 suv(vec3 a){return dot(vec3(1),a);}vec1 suv(vec2 a){return a.x+a.y;}//sum of vector
#define minx(a,b)mix(b,a,step(a.x,b.x))
#define manx(a,b)mix(a,-b,step(a.x,-b.x))
#define maxx(a,b)-minx(-a,-b)
vec1 miv(vec2 a){return min(a.y,a.x);}vec1 miv(vec3 a){return min(a.z,miv(a.xy));}vec1 miv(vec4 a){return min(miv(a.zw),miv(a.xy));}
#define mav(a)-miv(-a)
#define cs(a) vec2(cos(a),sin(a))

//fract(dot(1031))hash summer 2018 seems ot be generally superior to fract(sin())hashes
vec3 g3(vec1 a){return vec3(a);}
vec3 g3(vec2 a){return a.xyx;}
vec3 g3(vec3 a){return a;}
vec4 g4(vec1 a){return vec4(a);}
vec4 g4(vec2 a){return a.xyxy;}
vec4 g4(vec3 a){return a.xyzy;}
vec4 g4(vec4 a){return a;}
//hashes by David Hoskins,Creative Commons Attribution-ShareAlike 4.0 International Public License
//parent https://www.shadertoy.com/view/4djSRW
#define hs vec4(.1031,.1030,.0973,.1099)
//#define HASHSCALE3 vec3(443.897,441.423,437.195,444.129)//For smaller input rangers like audio tick or 0-1 UVs use these...
#define hout1(a)fract((a.x+a.y)*a.z)
#define hout2(a)fract((a.xx+a.yz)*a.zy)
#define hout3(a)fract((a.xxy+a.yzz)*a.zyx)
#define hout4(a)fract((a.xxyz+a.yzzw)*a.zywx)
#define h3mid(a)((a)+dot(a,a.yzx+19.19))
#define h4mid(a)((a)+dot(a,a.wzxy+19.19))
//hashes are named by output type,NEVER by input type
//hash1 mirrors at y=x and has strong banding on diagonals.
//only hash4 takes in vec4.all hash functions take vey1,v3c2,vec3 in (a vec4 generalizations is a mild overkill for most vec2,vec3 contexts)
#define hash1(a)hout1(h3mid(fract(hs.x*g3(a))))
#define hash2(a)hout2(h3mid(fract(hs.xyz*g3(a))))
#define hash3(a)hout3(h3mid(fract(hs.xyz*g3(a))))
#define hash4(a)hout4(h4mid(hs*g4(a)))
//not sure if its this shaders fault,likely a fract()error,but the avobe hsh gives bad lines.
//float hash1(float n){ return fract(sin(n)*1e4);}

#define ab012(a,b)(a+b*vec3(0,1,2))//desaturation.rgb kernel;b scales offset
//rainbow*()ro from purple to purple for range[0..1],this makes ab012()desaturate into semi-gaussian scattering.
vec3 rainbow(float a,float b){return u5(cos(2.*pi*ab012(a,b)));}//sine rainbow with offsets,desaturates colors for small b
vec3 rainbow2(float a,float b){return abs(u2(fract(ab012(a,b))));}//triangle rainbow with offsets,desaturates colors for small b
vec3 rainbow(float a){return rainbow(a,1./3.);}
vec3 rainbow2(float a){return rainbow2(a,1./3.);}










#define SAMPLES 64.
#define iterBayerMat 1
#define bayer2x2(a)(4-(a).x-((a).y<<1))%4

float boxSDF(vec2 p,vec2 s
){vec2 r=abs(p)-s
 ;return min(max(r.x,r.y),0.)+length(max(r,vec2(0)));}

vec3 colormap(float x
){//float s=sin(x*6.28)
 ;return vec3(1,vec2(-1,1)*sign(x))*.25+.25;}

void AddObj(inout float dist,inout vec3 color,float d,vec3 c
){if(dist>d){dist=d;color=c;}}

vec4 scene(vec2 u,vec2 m
){float dist=1e9;
 ;vec3 color=vec3(0)
 ;AddObj(dist,color,boxSDF(u-vec2(-3,1),vec2(1,1)),vec3(.6,.8,1.))
 ;AddObj(dist,color,length(u-vec2(3,1))- 1.,vec3(1,.9,.8))
 ;AddObj(dist,color,length(u-vec2(.3*sin(iTime),-2))- 0.5,vec3(0,.1,0))
 ;AddObj(dist,color,boxSDF(u-m,vec2(1.5,0.1)),vec3(.3,.1,.1))
 ;return vec4(color,dist);}

vec3 trace(vec2 p,vec2 dir,vec2 m
){for (int a=128;a>0;a--
){vec4 s=scene(p,m)
  ;if(s.w<1e-1)return s.xyz
  ;if(s.w>10.)return vec3(0)
  ;p+=dir*s.w;
 }return vec3(0);}

//return bayer matrix(bitwise operands for speed over compatibility)
float GetBayerFromCoordLevel(vec2 pixelpos//https://www.shadertoy.com/view/XtV3RG
){ivec2 p=ivec2(pixelpos);int a=0
 ;for(int i=0;i<iterBayerMat;i++
){a+=bayer2x2(p>>(iterBayerMat-1-i)&1)<<(2*i)
 ;}return float(a)/float(2<<(iterBayerMat*2-1));}

//float hash1(vec2 _st){return fract(sin(dot(_st.xy,vec2(12.9898,78.233)))*43758.5453123);}
void mainImage(out vec4 fragColor,vec2 u
){u=fra(u)//(u-(iResolution.xy*.5))/iResolution.y*ViewZoom
 ;vec2 m=vec2(0)
 ;if(iMouse.z<=0.)m.xy=vec2(.5)+vec2(cos(iTime),sin(iTime*1.61))*.3*ViewZoom
 ;else m=fra(iMouse.xy)
 ;vec3 c=vec3(0)
 ;float phi=sqrt(5.)*.5-.5
 ;for(float i=0.;i<SAMPLES;i++
){
  ;float scale=1.//pi //some values make more sense, i have no clue why-
  //;float t=(i+hash1(u.x-u.y+i+iTime))/SAMPLES*2.*pi
  ;float t=(i+GetBayerFromCoordLevel(u*phi*ViewZoom*iResolution.x+i+iTime*1.61)/scale)/SAMPLES*2.*pi*scale
  ;c+=trace(u,cs(t),m)
  ;}
 ;c/=SAMPLES
 ;fragColor=vec4(c*2.,1);}




