这里只展开fragment.glsl的代码,vertex都大差不离

varying vec3 v_position;
varying vec2 vUv;
void main(){
    vUv = uv;
    v_position = position;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position*0.4,1.0);
}

ed209

uniform vec2 u_resolution;
varying vec2 vUv;
uniform float u_time;


float stretch, gunsUp, gunsForward, edWalk, edTwist, edDown, edShoot, doorOpen, glow = 0.0;

// #define AA  // Enable this line if your GPU can take it!

struct MarchData {
	float d;
	vec3 mat; // RGB
	float specPower; // 0: None, 30.0: Shiny
};

mat2 rot(float a) {
	float c = cos(a),
	      s = sin(a);
	return mat2(c, s, -s, c);
}

float remap(float f, float in1, float in2, float out1, float out2) { return mix(out1, out2, clamp((f - in1) / (in2 - in1), 0., 1.)); }

float sdBox(vec3 p, vec3 b) {
	vec3 q = abs(p) - b;
	return length(max(q, 0.)) + min(max(q.x, max(q.y, q.z)), 0.);
}

float sdChamferedCube(vec3 p, vec3 r, float c) {
	float cube = sdBox(p, r);
	p.xz *= rot(.78525);
	r.xz *= -c / 1.41 + 1.41;
	return max(cube, sdBox(p, r));
}

float sdTriPrism(vec3 p, vec2 h) {
	vec3 q = abs(p);
	return max(q.z - h.y, max(q.x * .866025 + p.y * .5, -p.y) - h.x * .5);
}

float sdCappedCone(vec3 p, vec3 a, vec3 b, float ra, float rb) {
	float rba = rb - ra,
	      baba = dot(b - a, b - a),
	      papa = dot(p - a, p - a),
	      paba = dot(p - a, b - a) / baba,
	      x = sqrt(papa - paba * paba * baba),
	      cax = max(0., x - ((paba < .5) ? ra : rb)),
	      cay = abs(paba - .5) - .5,
	      f = clamp((rba * (x - ra) + paba * baba) / (rba * rba + baba), 0., 1.),
	      cbx = x - ra - f * rba,
	      cby = paba - f;
	return ((cbx < 0. && cay < 0.) ? -1. : 1.) * sqrt(min(cax * cax + cay * cay * baba, cbx * cbx + cby * cby * baba));
}

float sdCappedCylinder(vec3 p, float h, float r) {
	vec2 d = abs(vec2(length(p.xy), p.z)) - vec2(h, r);
	return min(max(d.x, d.y), 0.) + length(max(d, 0.));
}

float sdCapsule(vec3 p, vec3 a, vec3 b, float r) {
	vec3 pa = p - a,
	     ba = b - a;
	return length(pa - ba * clamp(dot(pa, ba) / dot(ba, ba), 0., 1.)) - r;
}

float sdOctogon(vec2 p, float r) {
	const vec3 k = vec3(-.92387953, .38268343, .41421356);
	p = abs(p);
	p -= 2. * min(dot(k.xy, p), 0.) * k.xy;
	p -= 2. * min(dot(vec2(-k.x, k.y), p), 0.) * vec2(-k.x, k.y);
	p -= vec2(clamp(p.x, -k.z * r, k.z * r), r);
	return length(p) * sign(p.y);
}

vec3 getRayDir(vec3 ro, vec3 lookAt, vec2 uv) {
	vec3 forward = normalize(lookAt - ro),
	     right = normalize(cross(vec3(0, 1, 0), forward));
	return normalize(forward + right * uv.x + cross(forward, right) * uv.y);
}

MarchData minResult(MarchData a, MarchData b) {
	if (a.d < b.d) return a;
	return b;
}

void setBodyMaterial(inout MarchData mat) {
	mat.mat = vec3(.36, .45, .5);
	mat.specPower = 30.;
}

float legWalkAngle(float f) { return sin(edWalk * 3.141 * 6. * f) * .2; }

float edZ() { return mix(5., -2., edWalk); }

float fireShock() { return abs(sin(edShoot * 78.5375)); }

float headSphere(vec3 p) { return (length(p / vec3(1, .8, 1)) - 1.) * .8; }

MarchData headVisor(vec3 p, float h, float bump) {
	bump *= sin(p.x * 150.) * sin(p.y * 150.) * .002;
	MarchData result;
	result.d = sdBox(p, vec3(1, h, 2));
	result.d = max(mix(result.d, headSphere(p), .57), -p.y) - bump;
	result.mat = vec3(.05);
	result.specPower = 30.;
	return result;
}

MarchData headLower(vec3 p) {
	vec3 op = p;

	// Start by mirroring the visor.
	MarchData r = headVisor(p * vec3(.95, -1.4, .95), 1., 0.);

	// Add the side panels.
	r.d = min(r.d, max(max(headVisor((p + vec3(0, .01, 0)) * vec3(.95), 1., 0.).d, p.y - .35), p.y * .625 - p.z - .66));

	// 'Wings'.
	p.xy *= rot(.075 * (gunsUp - 1.) * sign(p.x));
	p.x = abs(p.x) - 1.33;
	p.y -= .1 - p.x * .1;
	r.d = min(r.d, sdBox(p, vec3(.4, .06 * (1. - p.x), .3 - p.x * .2)));
	p = op;

	// Cut out a mouth grill.
	p.y = abs(abs(p.y + .147) - .0556) - .0278;
	r.d = max(r.d, -sdBox(p + vec3(0, 0, 1.5), vec3(mix(.25, .55, -op.y), .015, .1)));

	// 'Cheeks'.
	p = op;
	p.y = abs(p.y + .16) - .06;
	p.z -= -1.1;
	r.d = max(r.d, -max(max(sdCappedCylinder(p.xzy, 1., .03), -sdCappedCylinder(p.xzy, .55, 1.)), p.z + .2));
	setBodyMaterial(r);
	return r;
}

MarchData gunPod(vec3 p) {
	MarchData r;
	setBodyMaterial(r);
	p.yz += vec2(.1, .45);

	// Carousel.
	vec3 pp = p;
	pp.z = abs(pp.z) - .5;
	r.d = sdCappedCone(pp, vec3(0), vec3(0, 0, -.1), .35 - .1, .35);
	r.d = min(r.d, sdCappedCylinder(p, .35, .4));

	// Triangle nobble.
	pp = vec3(p.x, .28 - p.y, p.z);
	r.d = min(r.d, sdTriPrism(pp, vec2(.1, .5)));

	// Square outriggers.
	pp = p;
	pp.x = abs(p.x);
	pp.xy *= rot(.78525);
	float fs,
	      bump = sign(sin(pp.z * 33.3)) * .003,
	      d = sdBox(pp, vec3(.1 - bump, .38 - bump, .34)) - .02;

	// Barrels.
	pp = p - vec3(0, 0, -.6);
	pp.x = abs(pp.x) - .1;
	d = min(min(min(d, sdCappedCylinder(pp, .06, .15)), sdCappedCylinder(pp + vec3(0, .12, -.05), .06, .05)), sdBox(p + vec3(0, 0, .54), vec3(.1, .06, .04)));
	if (d < r.d) {
		d = max(d, -sdCappedCylinder(pp + vec3(0, 0, .1), .03, .2));
		r.d = d;
		r.mat = vec3(.02);
	}

	// Muzzle flash.
	fs = fireShock();
	if (fs > .5) {
		d = sdCappedCylinder(pp, .01 + pp.z * .05, fract(fs * 3322.423) * .5 + .9);
		if (d < r.d) {
			r.d = d;
			r.mat = vec3(1);
			glow += .1 / (.01 + d * d * 4e2);
		}
	}

	return r;
}

MarchData arms(vec3 p) {
	const vec3 wrist = vec3(1.5, 0, 0) - vec3(0, 0, .3);
	MarchData r;
	setBodyMaterial(r);

	// Position origin.
	p.x = abs(p.x);
	p.yz += vec2(.24, 0);
	p.xy *= rot(.15 * (gunsUp - 1.));

	// Shoulder and forearm.
	r.d = min(sdCapsule(p, vec3(0), vec3(1.5, 0, 0), .2), sdCapsule(p, vec3(1.5, 0, 0), wrist, .2));

	// Gunz.
	p -= wrist;
	p.z -= gunsForward * .15;
	return minResult(r, gunPod(p));
}

float toe(vec3 p) {
	p.yz += vec2(.1, .32);
	return max(sdBox(p, vec3(.3 + .2 * (p.z - .18) - p.y * .228, .3 + .2 * cos((p.z - .18) * 3.69), .35)), .1 - p.y);
}

float foot(vec3 p) {
	p.z += .8;
	p.yz *= rot(.86);
	float d = toe(p);
	p.xz *= rot(1.57);
	p.x -= .43;
	p.z = .25 - abs(p.z);
	return min(d, toe(p));
}

MarchData waist(vec3 p) {
	MarchData r;
	setBodyMaterial(r);
	p.y += .65;
	p.yz *= rot(-.2);
	float bump, d,
	      legAngle = legWalkAngle(1.);
	p.xy *= rot(legAngle * .3);
	vec3 pp = p;
	pp.y += .3;
	r.d = max(sdCappedCylinder(pp.zyx, .5, .5), p.y + .15);

	// Thorax.
	bump = .5 - abs(sin(p.y * 40.)) * .03;
	d = sdBox(p, vec3(bump, .15, bump));

	// Leg joins.
	bump = .3 - abs(sin(p.x * 40.)) * .03;
	pp.y += .18;
	d = min(d, sdCappedCylinder(pp.zyx, bump, .75));

	// Hips.
	pp.x = abs(pp.x);
	pp.yz *= rot(-.58525 + legAngle * sign(p.x));
	pp.x -= .98;
	r.d = min(r.d, max(sdCappedCylinder(pp.zyx, .4, .24), -pp.y));
	r.d = min(r.d, sdBox(pp, vec3(.24, .2, .14 + .2 * pp.y)));

	// Thigh pistons.
	p = pp;
	pp.xz = abs(pp.xz) - vec2(.12, .25);
	r.d = min(r.d, max(min(sdCappedCylinder(pp.xzy, .1, .325), sdCappedCylinder(pp.xzy, .05, .5)), pp.y));

	// 'Knees'.
	p.y += .68;
	r.d = min(r.d, sdBox(p, vec3(sign(abs(p.y) - .04) * .005 + .26, .2, .34)));
	if (d < r.d) {
		// Black segments.
		r.d = d;
		r.mat = vec3(.02);
	}

	return r;
}

MarchData legs(vec3 p) {
	MarchData r;
	setBodyMaterial(r);
	float silver,
	      legAngle = legWalkAngle(1.);
	p.z += .27;
	p.yz *= rot(legAngle * sign(p.x));
	p.z -= .27;
	p.y += .65;
	p.yz *= rot(-.2);
	p.xy *= rot(legAngle * .3);
	vec3 cp,
	     pp = p;
	pp.x = abs(pp.x);
	pp.y += .48;
	pp.yz *= rot(-.58525);
	pp.x -= .98;
	cp = pp;
	p = pp;
	pp.xz = abs(pp.xz) - vec2(.12, .25);
	p.y += .68;

	// Thighs.
	p.xy = abs(p.xy) - .12;
	silver = sdBox(p, vec3(.07, .05, 1.2));

	// Leg end cap.
	cp -= vec3(0, -.7, 0);
	r.d = sdBox(cp - vec3(0, 0, 1.15), vec3(.17, .17, .07)) - .04;

	// Shin.
	cp.z++;
	r.d = min(r.d, sdChamferedCube(cp.xzy, vec2(.28 - sign(abs(cp.z) - .3) * .01, .5).xyx, .18));

	// Feet.
	r.d = min(r.d, foot(cp));
	if (silver < r.d) {
		r.d = silver;
		r.mat = vec3(.8);
	}

	return r;
}

MarchData ed209(vec3 p) {
	p.yz += vec2(legWalkAngle(2.) * .2 + .1, -edZ());
	MarchData r = legs(p);
	float f = min(stretch * 2., 1.),
	      slide = f < .5 ? smoothstep(0., .5, f) : (1. - smoothstep(.5, 1., f) * .2);
	p.yz -= slide * .5;
	gunsUp = smoothstep(0., 1., clamp((stretch - .66) * 6., 0., 1.)); // 0.66-0.83
	gunsForward = smoothstep(0., 1., clamp((stretch - .83) * 6., 0., 1.)) // 0.83-1.0
	 + fireShock() * .5;
	r = minResult(r, waist(p));
	p.yz *= rot(.1 * (-edDown + legWalkAngle(2.) + smoothstep(0., 1., clamp((stretch - .5) * 6., 0., 1.)) - 1.)); // 0.5-0.66
	p.xz *= rot(edTwist * .2);
	return minResult(minResult(minResult(r, headLower(p)), headVisor(p, .8, 1.)), arms(p));
}

MarchData room(vec3 p) {
	const vec3 frameInner = vec3(2.8, 2.6, .1);
	MarchData r;
	r.mat = vec3(.4);
	r.specPower = 1e7;
	vec2 xy = p.xy - vec2(0, 2);
	p.x = abs(p.x);
	p.yz += vec2(.5, -3.4);
	float doorFrame, doorWidth, door, d,
	      doorHole = sdBox(p, frameInner + vec3(0, 0, 1)),
	      backWall = length(p.z - 8.);
	r.d = min(backWall, max(length(p.z), -doorHole + .1));
	if (r.d == backWall) {
		float ocp = min(abs(sdOctogon(xy, 2.6)), abs(sdOctogon(xy, 1.9)));
		ocp = min(max(ocp, min(.7 - abs(xy.x + 1.2), -xy.y)), max(abs(sdOctogon(xy, 1.2)), min(xy.x, .7 - abs(xy.y))));
		if (ocp < .3) r.mat = vec3(.39, .57, .71);
	}

	doorFrame = max(sdBox(p, frameInner + vec3(.4, .4, .1)), -doorHole);
	doorWidth = frameInner.x * .5;
	p.x -= frameInner.x;
	p.xz *= rot(doorOpen * 2.1);
	p.x += doorWidth;
	door = sdBox(p, vec3(doorWidth, frameInner.yz));
	p = abs(p) - vec3(doorWidth * .5, 1.1, .14);
	d = min(doorFrame, max(door, -max(sdBox(p, vec3(.45, .9, .1)), -sdBox(p, vec3(.35, .8, 1)))));
	if (d < r.d) {
		r.d = d;
		r.mat = vec3(.02, .02, .024);
		r.specPower = 10.;
	}

	return r;
}

// Map the scene using SDF functions.
MarchData map(vec3 p) {
	MarchData r = minResult(room(p), ed209(p));
	float gnd = length(p.y + 3.);
	if (gnd < r.d) {
		r.d = gnd;
		r.mat = vec3(.1);
	}

	return r;
}

float calcShadow(vec3 p, vec3 lightPos) {
	// Thanks iq.
	vec3 rd = normalize(lightPos - p);
	float res = 1.,
	      t = .1;
	for (float i = 0.; i < 30.; i++) {
		float h = map(p + rd * t).d;
		res = min(res, 12. * h / t);
		t += h;
		if (res < .001 || t > 25.) break;
	}

	return clamp(res, 0., 1.);
}

vec3 calcNormal(vec3 p, float t) {
	float d = .01 * t * .33;
	vec2 e = vec2(1, -1) * .5773 * d;
	return normalize(e.xyy * map(p + e.xyy).d + e.yyx * map(p + e.yyx).d + e.yxy * map(p + e.yxy).d + e.xxx * map(p + e.xxx).d);
}

// Quick ambient occlusion.
float ao(vec3 p, vec3 n, float h) { return map(p + h * n).d / h; }

/**********************************************************************************/
vec3 vignette(vec3 col, vec2 fragCoord) {
	vec2 q = fragCoord.xy / u_resolution.xy;
	col *= .5 + .5 * pow(16. * q.x * q.y * (1. - q.x) * (1. - q.y), .4);
	return col;
}

vec3 applyLighting(vec3 p, vec3 rd, float d, MarchData data) {
	vec3 sunDir = normalize(vec3(10, 10, -10) - p),
	     n = calcNormal(p, d);

	// Primary light.
	float primary = max(0., dot(sunDir, n)),
	      bounce = max(0., dot(-sunDir, n)) * .2,
	      spe = pow(max(0., dot(rd, reflect(sunDir, n))), data.specPower) * 2.,
	      fre = smoothstep(.7, 1., 1. + dot(rd, n)),
	      fog = exp(-length(p) * .05);

	// Combine.
	primary *= mix(.2, 1., calcShadow(p, vec3(10, 10, -10)));
	return mix(data.mat * ((primary + bounce) * ao(p, n, .33) + spe) * vec3(2, 1.6, 1.7), vec3(.01), fre) * fog;
}

vec3 getSceneColor(vec3 ro, vec3 rd) {
	// Raymarch.
	vec3 p;
	float g,
	      d = .01;
	MarchData h;
	for (float steps = 0.; steps < 120.; steps++) {
		p = ro + rd * d;
		h = map(p);
		if (abs(h.d) < .0015 * d) break;
		if (d > 64.) return vec3(0); // Distance limit reached - Stop.
		d += h.d; // No hit, so keep marching.
	}

	// Lighting.
	g = glow;
	return applyLighting(p, rd, d, h) + fireShock() * .3 + g;
}

void mainImage(out vec4 fragColor, vec2 fragCoord) {
	edWalk = 1.;
	edTwist = 0.;
	edDown = 0.;
	edShoot = 0.;
	doorOpen = 1.;
	stretch = 1.;

	// Camera.
	vec3 ro, lookAt, col;
	float startScene, endScene, dim,
	      time = mod(u_time, 55.);
	if (time < 12.) {
		startScene = 0.;
		endScene = 12.;
		edWalk = 0.;
		ro = vec3(0, -1.5, -.625);
		lookAt = vec3(0, -1, edZ());
		doorOpen = smoothstep(0., 1., time / 5.);
		stretch = remap(time, 7., 10., 0., 1.);
	}
	else if (time < 25.) {
		startScene = 12.;
		endScene = 25.;
		float t = time - startScene;
		edWalk = smoothstep(0., 1., remap(t, 3., 8., 0., 1.));
		ro = vec3(-.5 * cos(t * .7), .5 - t * .1, edZ() - 3.);
		lookAt = vec3(0, 0, edZ());
	}
	else if (time < 29.) {
		startScene = 25.;
		endScene = 29.;
		ro = vec3(-2, .5 + (time - startScene) * .1, edZ() - 3.);
		lookAt = vec3(0, 0, edZ());
	}
	else if (time < 37.) {
		startScene = 29.;
		endScene = 37.;
		float t = time - startScene;
		ro = vec3(1.5, -1. - t * .05, edZ() - 5.);
		lookAt = vec3(0, -1, edZ());
		stretch = remap(t, 2., 5., 1., 0.);
	}
	else if (time < 55.) {
		startScene = 37.;
		endScene = 55.;
		float t = time - startScene;
		ro = vec3(-1.8, -.5, edZ() - 2.5);
		stretch = remap(t, 2., 3., 0., 1.) - remap(t, 11.5, 14.5, 0., 1.);
		lookAt = vec3(0, stretch * .5 - .5, edZ());
		edTwist = remap(t, 3., 3.2, 0., 1.) * stretch;
		edDown = remap(t, 3.2, 3.4, 0., 1.) * stretch;
		edShoot = t <= 9.5 ? remap(t, 4., 9.5, 0., 1.) : 0.;
	}

	dim = 1. - cos(min(1., 2. * min(abs(time - startScene), abs(time - endScene))) * 1.5705);
	col = vec3(0);
#ifdef AA
	for (float dx = 0.; dx <= 1.; dx++) {
		for (float dy = 0.; dy <= 1.; dy++) {
			vec2 coord = fragCoord + vec2(dx, dy) * .5;
#else
			vec2 coord = fragCoord;
#endif
			coord += (fract(fireShock() * vec2(23242.232, 978.23465)) - .5) * 10.;
			vec2 uv = (coord - .5 * u_resolution.xy) / u_resolution.y;
			col += getSceneColor(ro, getRayDir(ro, lookAt, uv));
#ifdef AA
		}
	}

	col /= 4.;
#endif

	// Output to screen.
	fragColor = vec4(vignette(pow(col * dim, vec3(.4545)), fragCoord), 1);
}

void main()
{
  mainImage(gl_FragColor,vUv * u_resolution.xy);
}

fractalCity

uniform float u_time;
uniform vec2 u_resolution;
uniform float u_frame;
varying vec3 v_position;
varying vec2 vUv;

#define R u_resolution
#define repeat(p,r)(mod(p,r)-r/2.)

mat2 rot(float a){return mat2(cos(a),-sin(a),sin(a),cos(a));}

vec3 look(vec3 from,vec3 at,vec2 uv,float fov)
{
  vec3 z=normalize(at-from);
  vec3 x=normalize(cross(z,vec3(0,1,0)));
  vec3 y=cross(x,z);
  return normalize(z*fov+uv.x*x+uv.y*y);
}

const uint k=1103515245U;

vec3 hash(uvec3 x)
{
  x=((x>>8U)^x.yzx)*k;
  x=((x>>8U)^x.yzx)*k;
  x=((x>>8U)^x.yzx)*k;
  return vec3(x)*(1./float(0xffffffffU));
}

const float speed=.05;
const float falloff=1.75;
const float range=.5;
const float count=8.;

// globals
vec3 pp,ppp;
float mat,glow;


float map(vec3 p)
{
   float dist = 100.;
   float shape = 100.;
   vec3 pos = p;
   pp = p;
   ppp = p;// travel
   float px=p.x-u_time*speed;
   float ix=floor(px);
   p.x=repeat(px,1.); 
   // city
   float a=1.;
   float angle=196.+ix;
   for(float i=0.;i<count;++i)
    {
        p.xz*=rot(angle/a);
        p=abs(p)-range*a;
        shape=max(p.x,max(p.y,p.z));
        mat=shape<dist?i:mat;
        pp=i==7.?p:pp;
        ppp=i==6.?p:ppp;
        dist=min(dist,shape);
        a/=falloff;
    }
    dist=-dist;
    
    // columns
    shape=max(length(pp.xz)-.001,dist-.005);
    dist=min(dist,shape);
    
    // lights
    shape=max(length(ppp.xy)-.001,dist-.001);
    glow+=.0001/max(.0005,shape);
    
    // crop
    dist=max(dist,abs(pos.y-.1)-.2);
    
    return dist;
}

// from Inigo Quilez
float shadow(vec3 pos,vec3 at,float k)
{
  vec3 dir=normalize(at-pos);
  float maxt=length(at-pos);
  float f=1.;
  float t=.002;
  for(float i=0.;i<=1.;i+=1./30.)
{
    float dist=map(pos+dir*t);
    if(dist<.001)return 0.;
      f=min(f,k*dist/t);
      t+=dist;
      if(t>=maxt)break;
}
    return f;
}

void rect(out vec4 fragColor,in vec2 fragCoord){
fragColor=vec4(0.,0.,0.,0.); 
   const float frames=3.;
    for(float frame=0.;frame<frames;++frame)
{
        // coordinates
    vec2 uv=fragCoord/R.xy;
    vec2 p=2.*(fragCoord-R.xy/2.)/R.y;    
        // anti aliasing
        float aa=6.28*frame/frames;
        p+=vec2(cos(aa),sin(aa))/R.xy;
        
        vec3 pos=vec3(.04,-.02,.09);
        vec3 ray=look(pos,vec3(0,0,0),p,4.);
        vec3 rng=hash(uvec3(fragCoord,float(u_frame)+frame*196.));
        
        // init globals
        glow=0.;
        mat=0.;
        // raymarch
        float total=0.;
        float steps=0.;
        const float count=100.;
        const float max_dist=4.;
        for(steps=count;steps>0.;--steps){
            float dist=map(pos);
            if(dist<.001*total||total>max_dist)break;
            dist*=.9+.1*rng.z;
            total+=dist;
            pos+=ray*dist;
        }
        vec4 result;
        if(total<max_dist)
        {
            // lighting
            float shade=steps/count;
            vec3 sun=normalize(vec3(0,1,.2));
            vec3 palette=.5+.5*cos(vec3(1,2,3)*5.+pos.z*6.+pos.y*6.);
            vec3 color=vec3(1.5);
            color*=sin(mat+1.)*.25+.75;
            color*=step(.01,ppp.z)*.25+.75;
            color*=step(pp.y,-.005)*.25+.75;
            color+=palette*clamp(.1/abs(mat-10.),0.,1.)*.9;
            color+=palette*glow;
            color*=shade;
            color*=.4+.6*shadow(pos,sun,100.);
            result=vec4(color,1);
        }
        else
        {
            // sky
            vec3 color=.5+.5*cos(vec3(1,2,3)*5.+uv.y*2.+2.);
            result=vec4(color,1);
        }
        
        // sum it up
        fragColor+=result/frames;
    }
}

void main()
{
  rect(gl_FragColor,vUv * u_resolution.xy);
}

lightSaberDuel


uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
uniform int u_frame;

// #define FOCAL_LENGTH 1.2
// #define MOVE_SPEED 20.
// #define MAX_STEPS 256
// #define MIN_DIST.01
// #define MAX_DIST 75.
// #define AMBIANT_LIGHT.01
// #define DAY_LENGTH 15.

// #define PI 3.14159265359

// #define TWO_EGGS

// #define QUALITY_MEDIUM

// #if defined(QUALITY_HIGH)

// #define VOL_SHADOW_STEPS 5.
// #define MIN_STEP_BIAS.3
// #define VOL_FOG 1
// #define VOL_SHADOW 1
// #define LIGHT_QUALITY 1

// #elif defined(QUALITY_MEDIUM)

// #define VOL_SHADOW_STEPS 2.
// #define MIN_STEP_BIAS.6
// #define VOL_FOG 1
// #define VOL_SHADOW 1
// #define LIGHT_QUALITY 1

// #elif defined(QUALITY_LOW)

// #define VOL_SHADOW_STEPS 1.
// #define MIN_STEP_BIAS.9
// #define VOL_FOG 1
// #define VOL_SHADOW 0
// #define LIGHT_QUALITY 0

// #elif defined(QUALITY_OFF)

// #define VOL_SHADOW_STEPS 1.
// #define MIN_STEP_BIAS 1.
// #define VOL_FOG 0
// #define VOL_SHADOW 0
// #define LIGHT_QUALITY 0

// #endif

// #define LASER_STR 1.5
// #define LASER_CORE vec3(.5)
// #define LASER_LIGHT_STR 1.5
// #define PURPLE vec3(.5,0.,1.5)
// #define GREEN vec3(0.,1.,0.)
// #define BLUE vec3(0.,0.,1.)*2.
// #define RED vec3(1.,0.,0.)*1.5
// #define YELLOW vec3(.6,.6,0.)

// #define JEDI GREEN
// #define SITH RED

// #define JEDI_SABER_NOISE 2.
// #define SITH_SABER_NOISE 5.

// vec3 zero=vec3(0.,0.,0.);

// vec3 projectionUp;
// vec3 projectionRight;
// vec3 projectionForward;
// vec3 projectionCenter;
// vec3 cameraOffset;
// float dayProgress;
// float minSurfaceDist;

// vec4 plane=vec4(vec3(0.,1.,0.),1.);
// vec3 sunLightPos;

// vec4 groundColor=vec4(vec3(.08),.7);
// vec4 handleColor=vec4(vec3(.1),.3);
// vec3 sunLightColor;
// vec3 skyColor;
// vec3 fogColor;

// float s_pixelRand=0.;
// float s_time=0.;

// float mapToRange(float fromMin,float fromMax,float toMin,float toMax,float val)
// {
//     val=max(fromMin,(min(fromMax,val)));
//     float fromSize=fromMax-fromMin;
//     val=(val-fromMin)/fromSize;
//     return mix(toMin,toMax,val);
// }

// vec3 noise3(in vec3 x)
// {
//     return texture2D(iChannel0,x.xy/x.z,0.).xyz;
// }

// #if VOL_FOG

// float layeredNoise(vec3 p)
// {
//     float f;
//     f=.5000*texture2D(iChannel1,p).x;
//     p=p*2.;
//     f+=.2500*texture2D(iChannel1,p).x;
//     p=p*2.;
//     f+=.1250*texture2D(iChannel1,p).x;
//     p=p*2.;
//     f+=.0800*texture2D(iChannel1,p).x;
//     p=p*2.;
//     f+=.0625*texture2D(iChannel1,p).x;
//     p=p*2.;
    
//     return f;
// }

// #define CONSTANT_FOG.03
// // To simplify: wavelength independent scattering and extinction
// float atmThickness(in vec3 pos)
// {
//     float disp1=.5;
//     float disp2=.5;
    
//     //disp1 = mapToRange(0.5, 1.0, 0.1, 1.0, layeredNoise(pos.xz*0.015 + s_time*0.008));
//     disp1=mapToRange(.3,1.,.1,1.,layeredNoise(pos*.02-vec3(0.,1.,0.)*s_time*.01));
//     //float noise = clamp(mapToRange(0.4, 0.8, 0.0, 1.0, disp2),0.0,1.0);
//     float fogMax=-1.-smoothstep(8.,-3.,length(pos.xz));
//     float fogMin=fogMax+disp1*3.;
//     float heightFog=smoothstep(fogMin,fogMax,pos.y);
    
//     heightFog=min(1.,heightFog*3.);
    
//     return CONSTANT_FOG+heightFog*2.;
// }

// float phaseFunctionVal=1./(4.*PI);
// #define PHASE_FUNC phaseFunctionVal

// float volumetricShadow(in vec3 from,in vec3 dir)
// {
//     float shadow=1.;
//     float cloud=0.;
//     float dd=1./VOL_SHADOW_STEPS;
//     vec3 pos;
//     for(float s=.5;s<VOL_SHADOW_STEPS-.1;s+=1.)// start at 0.5 to sample at center of integral part
//     {
//         pos=from+dir*(s/VOL_SHADOW_STEPS);
//         cloud=atmThickness(pos);
//         shadow*=exp(-cloud*dd);
//     }
//     return shadow;
// }

// #endif

// vec2 pixelToNormalizedspace(vec2 pixel)
// {
//     vec2 res;
//     res.x=pixel.x*2./u_resolution.x-1.;
//     res.y=pixel.y*2./u_resolution.y-1.;
//     res.y*=u_resolution.y/u_resolution.x;//correct aspect ratio
//     return res;
// }

// float fCapsule(vec3 p,float r,float c){
//     return mix(length(p.xz)-r,length(vec3(p.x,abs(p.y)-c,p.z))-r,step(c,abs(p.y)));
// }

// float fSphere(vec3 d,float r)
// {
//     return length(d)-r;
// }

// float fPlane(vec4 plane,vec3 point)
// {
//     return abs(dot(plane,vec4(point,1.)));
// }

// // Hexagonal prism, circumcircle variant
// float fHexagonCircumcircle(vec3 p,vec2 h){
//     vec3 q=abs(p);
//     //return max(q.y - h.y, max(q.x*sqrt(3)*0.5 + q.z*0.5, q.z) - h.x);
//     //this is mathematically equivalent to this line, but less efficient:
//     return max(q.y-h.y,max(dot(vec2(cos(PI/3.),sin(PI/3.)),q.zx),q.z)-h.x);
// }

// // Repeat in two dimensions
// vec2 pMod2(inout vec2 p,vec2 size){
//     vec2 c=floor((p+size*.5)/size);
//     p=mod(p+size*.5,size)-size*.5;
//     return c;
// }

// //////////////////////////////

// float linearstep(float e1,float e2,float v)
// {
//     v=clamp(v,e1,e2);
//     return(v-e1)/(e2-e1);
// }

// float fEgg(vec3 d,float r,vec3 deform)
// {
//     return length(d/deform)-r;
// }

// #define IMAT3 mat3(vec3(1.,0.,0.),vec3(0.,1.,0.),vec3(0.,0.,1.))

// float maxDist=100.;

// //constants
// float handRSize=.15;
// float handLSize=.15;
// float footRSize=.22;
// float footLSize=.22;
// vec3 eyeRPos=vec3(.2,.2,0.);
// vec3 eyeLPos=vec3(-.2,.2,0.);
// float eyeRSize=.105;
// float eyeLSize=.105;
// vec3 mouthPos=vec3(0.,0.,-.03);
// float mouthSize=.1;
// float mouthXRot=PI*.325;
// float handleRadius=.1;
// float handleLen=.35;
// vec4 bodyColor=vec4(vec3(.1),.8);
// vec4 eyeColor=vec4(vec3(.9),.1);
// vec4 eyeInsideColor=vec4(vec3(.1),.1);
// vec4 mouthColor=vec4(1.,1.,0.,.1);

// struct StickmanData
// {
//     vec3 stickmanPos;
//     //relative to stickManPos
//     vec3 bodyPos;
//     vec3 bodyDeform;
//     vec3 headPos;
//     vec3 handRPos;
//     vec3 handLPos;
//     vec3 handRDeform;
//     vec3 handLDeform;
//     mat3 handRRot;
//     mat3 handLRot;
    
//     vec3 footRPos;
//     vec3 footLPos;
//     mat3 footRRot;
//     mat3 footLRot;
//     vec3 footRDeform;
//     vec3 footLDeform;
    
//     mat3 invBodyRot;
//     mat3 invStickmanRot;
//     mat3 invMouthRot;
    
//     //relative to headPos
    
//     vec3 eyeRDeform;
//     vec3 eyeLDeform;
    
//     vec3 mouthDeform;
    
//     vec3 saberTarget;
//     vec3 saberPos;
//     float saberRadius;
//     float saberLen;
//     float saberNoise;
//     mat3 invSaberRot;
    
//     vec3 laserColor;
//     vec3 laserLight;
// };

// StickmanData jediData;
// StickmanData sithData;

// struct FieldData
// {
//     vec3 saberDiff;
//     vec3 saberOffset;
//     vec3 handleOffset;
//     float fSaber;
// };

// FieldData jediFieldData;
// FieldData sithFieldData;

// void rotationZ(float r,out mat3 mat)
// {
//     mat[0].x=cos(r);mat[0].y=sin(r);mat[0].z=0.;
//     mat[1].x=-sin(r);mat[1].y=cos(r);mat[1].z=0.;
//     mat[2].x=0.;mat[2].y=0.;mat[2].z=1.;
// }

// void rotationY(float r,out mat3 mat)
// {
//     mat[0].x=cos(r);mat[0].y=0.;mat[0].z=-sin(r);
//     mat[1].x=0.;mat[1].y=1.;mat[1].z=0.;
//     mat[2].x=sin(r);mat[2].y=0.;mat[2].z=cos(r);
// }

// void rotationX(float r,out mat3 mat)
// {
//     mat[0].x=1.;mat[0].y=0.;mat[0].z=0.;
//     mat[1].x=0.;mat[1].y=cos(r);mat[1].z=sin(r);
//     mat[2].x=0.;mat[2].y=-sin(r);mat[2].z=cos(r);
// }

// //wonderfull function from iq's article
// //https://iquilezles.org/articles/noacos
// void rotationAlign(vec3 d,vec3 z,out mat3 mat)
// {
//     vec3 v=cross(z,d);
//     float c=dot(z,d);
//     float k=1./(1.+c);
    
//     mat=mat3(v.x*v.x*k+c,v.y*v.x*k-v.z,v.z*v.x*k+v.y,
//         v.x*v.y*k+v.z,v.y*v.y*k+c,v.z*v.y*k-v.x,
//     v.x*v.z*k-v.y,v.y*v.z*k+v.x,v.z*v.z*k+c);
// }

// //ugly hack to get partial look at rotation, works well enough
// void rotationAlign(vec3 targ,vec3 dir,float i,out mat3 mat)
// {
//     vec3 diff=targ-dir;
//     if(dot(diff,diff)>.1)
//     {
//         vec3 mixed=normalize(mix(targ,dir,1.-i));
//         rotationAlign(mixed,dir,mat);
//     }
//     else
//     {
//         mat=IMAT3;
//     }
// }

// //pre-computes field data that doesn't change during the raymarching
// void computeFieldData(in StickmanData data,out FieldData fieldData)
// {
//     fieldData.saberDiff=data.bodyPos+data.saberPos*data.bodyDeform;
//     fieldData.saberOffset=vec3(0.,-data.saberLen-handleLen,0.);
//     fieldData.handleOffset=vec3(0.,handleLen*.5,0.);
//     fieldData.fSaber=MAX_DIST;
// }

// float fSaber(vec3 d,in StickmanData data,in FieldData fieldData)
// {
//     vec3 saberDiff=d-fieldData.saberDiff;
//     saberDiff=data.invSaberRot*saberDiff;
//     float saber=fCapsule(saberDiff+fieldData.saberOffset,
//         data.saberRadius
//         *(pow(mapToRange(data.saberLen*1.95,data.saberLen*2.+handleLen,1.,.01,saberDiff.y),.35))
//         *mapToRange(0.,1.,.85,1.,sin(s_time*30.-saberDiff.y*data.saberNoise)),
//     data.saberLen);
    
//     return saber;
// }

// float fHandle(vec3 d,in StickmanData data,in FieldData fieldData)
// {
//     vec3 saberDiff=d-fieldData.saberDiff;
//     saberDiff=data.invSaberRot*saberDiff;
//     float handle=fCapsule(saberDiff+fieldData.handleOffset,
//         handleRadius,
//     handleLen);
//     return handle;
// }

// vec4 fStickman(vec3 d,in StickmanData data,in FieldData fieldData,inout float minDist)
// {
//     float r=s_time*3.14*.5;
    
//     vec3 bodyD=data.invBodyRot*(d-data.bodyPos);
//     vec3 fixedBodyD=d-data.bodyPos;
//     //main body
//     float body=fEgg(bodyD,1.,data.bodyDeform);
//     float subBody=fEgg(bodyD+vec3(0.,.6,.5),1.,data.bodyDeform*vec3(.8,.8,.8));
//     //eyes
//     float eye=fEgg(bodyD-(data.headPos+eyeLPos)*data.bodyDeform,eyeLSize,data.eyeLDeform);
//     eye=min(eye,fEgg(bodyD-(data.headPos+eyeRPos)*data.bodyDeform,eyeRSize,data.eyeRDeform));
    
//     float subEye=fEgg(bodyD-(data.headPos+eyeLPos+vec3(.07,-.03,-.1))*data.bodyDeform,
//     eyeLSize,data.eyeLDeform*vec3(.3,.4,.3));
//     subEye=min(subEye,fEgg(bodyD-(data.headPos+eyeRPos+vec3(-.07,-.03,-.1))*data.bodyDeform,
//     eyeLSize,data.eyeLDeform*vec3(.3,.4,.3)));
//     eye=min(eye,subEye);
    
//     //mouth
//     float mouth=fEgg(
//         data.invMouthRot*(bodyD-(data.headPos+mouthPos)*data.bodyDeform),
//     mouthSize,data.mouthDeform);
    
//     //hands
//     float hands;
//     hands=fEgg(data.handRRot*(fixedBodyD-data.handRPos*data.bodyDeform),
// handRSize,data.handRDeform);
// hands=min(hands,fEgg(data.handLRot*(fixedBodyD-data.handLPos*data.bodyDeform),
// handLSize,data.handLDeform));
// //feet
// float feet;
// feet=fEgg(data.footRRot*(d-(data.footRPos)),
// footRSize,data.footRDeform);
// feet=min(feet,fEgg(data.footLRot*(d-(data.footLPos)),
// footLSize,data.footLDeform));
// //saber
// float saber=fieldData.fSaber;//fSaber(d, data, fieldData);
// float handle=fHandle(d,data,fieldData);

// minDist=min(minDist,body);
// minDist=min(minDist,eye);
// minDist=min(minDist,mouth);
// minDist=min(minDist,hands);
// minDist=min(minDist,feet);
// minDist=min(minDist,saber);
// minDist=min(minDist,handle);

// vec4 color=vec4(0.);//egg bolor
// color+=mix(bodyColor,vec4(vec3(.9),.8),step(subBody,body))*step(body,minDist);
// color+=mix(eyeColor,bodyColor,step(subEye,eye))*step(eye,minDist);
// color+=bodyColor*step(hands,minDist);
// color+=bodyColor*step(feet,minDist);
// color+=mouthColor*step(mouth,minDist);
// color+=vec4(data.laserColor,0.)*step(saber,minDist);
// color+=handleColor*step(handle,minDist);

// return color;
// }

// //transition functions
// float pingPong(float p)
// {
// return 1.-abs(p*2.-1.);
// }

// float minHandDist=1.2;
// float maxHandDist=1.7;

// void invKinOneHand(float i,mat3 alignRot,inout StickmanData data)
// {
// data.handLPos=data.handLPos*alignRot;
// }

// void invKinTwoHand(float i,mat3 alignRot,inout StickmanData data)
// {
// vec3 f=vec3(0.,0.,1.);
// vec3 dir=normalize(mix(f,data.invSaberRot*f,i));

// mat3 rot;
// rotationAlign(f,dir,rot);
// data.handLRot=data.handLRot*rot;

// vec3 target=data.handRPos+vec3(0.,-.3,0.)*data.invSaberRot;
// float l=mix(length(data.handLPos),max(length(target),minHandDist),i);
// data.handLPos=normalize(mix(data.handLPos,target,pow(i,.5)))*l;
// }

// vec3 neutralTarget=vec3(0.,0.,-1.);
// float ll=1.;//leg length ratio

// void invKinematics(float twoHanded,float hit,inout StickmanData data)
// {
// data.saberTarget=normalize(data.saberTarget);
// mat3 alignRot;

// //rotate saber
// rotationAlign(data.saberTarget,vec3(0.,1.,0.)*data.invSaberRot,hit,alignRot);
// data.invSaberRot=data.invSaberRot*alignRot;

// //move hand/handle
// data.saberPos=mix(data.saberPos,maxHandDist*normalize(data.saberPos),hit);
// rotationAlign(data.saberTarget,neutralTarget,.8,alignRot);
// vec3 armTarget=neutralTarget*alignRot;
// rotationAlign(armTarget,normalize(data.saberPos),hit,alignRot);
// data.saberPos*=alignRot;

// data.saberPos=max(length(data.saberPos),minHandDist)*normalize(data.saberPos);
// data.handRPos=data.saberPos;
// data.handRRot=data.invSaberRot;
// //move body stance
// data.bodyPos=mix(data.footRPos,data.footLPos,.5)+vec3(0.,data.bodyPos.y,.1);
// //turn body
// vec3 bodyRestDir=normalize(vec3(1.,-.5,-.5));
// vec3 saberDir=normalize(mix(bodyRestDir,data.saberPos,.3));
// rotationAlign(saberDir,bodyRestDir,alignRot);
// data.invBodyRot*=alignRot;
// //back hand rot
// saberDir=normalize(mix(bodyRestDir,data.saberPos,1.-twoHanded));
// rotationAlign(saberDir,bodyRestDir,alignRot);

// //squint eyes while you hit, just because ....
// data.eyeLDeform.y*=1.-hit*.4;
// data.eyeRDeform.y*=1.-hit*.5;

// invKinOneHand(1.-twoHanded,alignRot,data);
// invKinTwoHand(twoHanded,alignRot,data);
// }

// float frontLoop(float i,float t,inout StickmanData data)
// {
// float dur=1.;
// float r=mod(t,dur)/dur;
// float p=pingPong(r)*i;

// mat3 rotY;
// rotationY(PI*i*-.15,rotY);

// mat3 rotX;
// rotationX(PI*2.*r*i,rotX);

// data.invSaberRot=rotX*data.invSaberRot*rotY;

// vec3 offset=vec3(0.,.7,.7)*.4*data.invSaberRot;
// data.saberPos.x+=.7*i;
// data.saberPos.y+=.6*i;
// data.saberPos.z+=.3*i;
// data.saberPos-=offset;

// return 0.;
// }

// float backLoop(float i,float t,inout StickmanData data)
// {
// float dur=1.;
// float r=mod(t,dur)/dur;
// float p=pingPong(r)*i;

// mat3 rotY;
// rotationY(PI*i*-.1,rotY);

// mat3 rotX;
// rotationX(PI*2.*r*i,rotX);

// data.invSaberRot=rotX*data.invSaberRot*rotY;

// vec3 offset=vec3(0.,.65,.7)*.3*data.invSaberRot;

// data.saberPos.y+=.55*i;
// data.saberPos-=offset;

// return 0.;
// }

// float nullMove(float i,float m,inout StickmanData data)
// {
// return 0.;
// }

// float nullPose(float i,inout StickmanData data)
// {
// return 0.;
// }

// float whirlingHit(float i,float m,inout StickmanData data)
// {
// float p1d=.3;
// float p2d=.4;
// float p3d=.3;

// float t=i;
// //arming part
// float p1=smoothstep(0.,p1d,t);
// //hitting part
// float p2=linearstep(p1d,p1d+p2d,t);
// p2=min(m,p2);
// //back to rest part
// float p3=linearstep(p1d+p2d,p1d+p2d+p3d,t);

// //move the target on trajectory
// vec3 start=vec3(.8,-.3,.3);
// vec3 end=vec3(-.5,-.1,-.45);
// vec3 target=mix(start,end,p2);
// target.y+=.3*pingPong(p2);
// //target = mix(target, neutralTarget, pow(p3, 0.4));
// data.saberTarget=mix(data.saberTarget,target,p1);

// //stance
// data.footRPos=mix(data.footRPos,ll*vec3(.4,.1,data.footLPos.z+1.2),(p1-p3));
// data.footRPos=mix(data.footRPos,ll*vec3(.4,.1,data.footLPos.z-1.2),pow(p2-p3,2.));
// data.footRPos.y+=pingPong(p1-p3)*ll*.1;
// //footRPos.y += pingPong(p2 - p3)*ll*0.1;

// float landing=pingPong(linearstep(p1d+p2d*.7,p1d+p2d+p3d*.5,t));
// float takeoff=1.-pow(1.-(smoothstep(0.,p1d*.6,t)-smoothstep(p1d*.6,p1d+p2d*.1,t)),2.);
// float jump=1.-pow(1.-(smoothstep(p1d,p1d+p2d*.5,t)-smoothstep(p1d+p2d*.5,p1d+p2d,t)),3.);

// data.bodyPos.y+=-takeoff*.3+jump*.4-landing*.2;
// data.bodyDeform.y+=-takeoff*.1+jump*.05-landing*.1;
// data.stickmanPos.y+=jump*1.;
// //footRPos.y -= jump*0.4;
// data.footLPos.y-=jump*.4;

// float r=smoothstep(p1d,p1d+p2d,t);
// mat3 rotY;
// rotationY(PI*-2.*r,rotY);

// mat3 rotX;
// rotationX(PI*.1*pow((p1+jump)*.5,2.),rotX);

// data.invStickmanRot=rotY*rotX*data.invStickmanRot;

// return p1-p3;
// }

// float forwardHit(float i,float m,inout StickmanData data)
// {
// float p=step(i,.5)*pow(i*2.,2.)+step(.5,i)*smoothstep(1.,.5,i);//pingPong(i);
// data.saberTarget=step(i,.001)*data.saberTarget+step(.001,i)*vec3(.3,0.,-2.);

// float mp=min(m,p);
// //stance
// data.footRPos=mix(data.footRPos,ll*vec3(.4,.1,data.footLPos.z-1.5),mp);
// data.footRPos.y+=pingPong(p)*ll*.1;
// return mp;
// }

// float upDownHit(float i,float m,inout StickmanData data)
// {
// float p1d=.2;
// float p2d=.6;
// float p3d=.2;

// float t=i;
// //arming part
// float p1=smoothstep(0.,p1d,t);
// float p2=1.-pow(1.-linearstep(p1d,p1d+p2d,t),1.);
// p2=min(m,p2);
// float p3=linearstep(p2d,p1d+p2d+p3d,t);

// //move the target on trajectory
// vec3 start=vec3(.8,.35,.3);
// vec3 end=vec3(-1.,-.45,-.45);
// vec3 target=mix(start,end,p2);//mix(mix(start, end, p2), neutralTarget, pow(p3, 0.4));
// data.saberTarget=mix(data.saberTarget,target,p1);

// //stance
// data.footRPos=mix(data.footRPos,ll*vec3(.4,.1,data.footLPos.z-1.2),(p1-p3));
// data.footRPos.y+=pingPong(p1-p3)*ll*.1;
// return p1-p3;
// }

// float parryUpRight(float i,float m,inout StickmanData data)
// {
// float p=1.-pow(1.-pingPong(i),4.);

// mat3 alignRot;
// vec3 restTarget=vec3(0.,1.,0.)*data.invSaberRot;
// vec3 armTarget=vec3(-1.,.15,-.1);
// rotationAlign(armTarget,restTarget,p,alignRot);
// data.invSaberRot=data.invSaberRot*alignRot;

// data.saberPos=mix(data.saberPos,vec3(.6,.42,-1.7),p);

// //squint eyes while you parry, just because ....
// data.eyeLDeform.y*=1.-p*.4;
// data.eyeRDeform.y*=1.-p*.6;

// //stance
// data.footRPos=mix(data.footRPos,ll*vec3(.8,.1,data.footRPos.z+.5),p);
// data.footRPos.y+=pingPong(p)*ll*.1;
// return 0.;
// }

// float parryDownLeft(float i,float m,inout StickmanData data)
// {
// float p=1.-pow(1.-pingPong(i),4.);

// mat3 alignRot;
// vec3 restTarget=vec3(0.,1.,0.)*data.invSaberRot;
// vec3 saberTarget=vec3(-.2,1.,-.5);
// rotationAlign(saberTarget,restTarget,p,alignRot);
// data.invSaberRot=data.invSaberRot*alignRot;

// data.saberPos=mix(data.saberPos,vec3(-.9,-.5,-1.4),p);

// //squint eyes while you parry, just because ....
// data.eyeLDeform.y*=1.-p*.4;
// data.eyeRDeform.y*=1.-p*.6;

// //stance
// data.footRPos=mix(data.footRPos,ll*vec3(.7,.1,data.footRPos.z+.5),p);
// data.footRPos.y+=pingPong(p)*ll*.1;
// return 0.;
// }

// void iddle(float t,float i,inout StickmanData data)
// {
// //mouth
// float dur=3.;
// float p;
// //p = pingPong(mod(t, dur)/dur)*i;
// //mouthDeform *= 0.9 + 0.2*p;
// //body
// p=pingPong(mod(t-.1,dur)/dur)*i;
// data.bodyDeform*=.975+.025*p;
// //hands
// float r=p*PI*-.07;
// data.handRRot=data.handRRot*mat3(vec3(cos(r),sin(r),0.),
// vec3(-sin(r),cos(r),0.),
// vec3(0.,0.,1.));
// r=-r;
// data.handLRot=data.handLRot*mat3(vec3(cos(r),sin(r),0.),
// vec3(-sin(r),cos(r),0.),
// vec3(0.,0.,1.));
// //eyes
// dur=5.;
// p=pingPong(smoothstep(dur-.3,dur,mod(t,dur)))*i;
// data.eyeRDeform.y*=1.-p;
// data.eyeLDeform.y*=1.-p;
// }

// float poseSaberSide(float i,inout StickmanData data)
// {
// data.saberPos=mix(data.saberPos,vec3(1.,-.2,-.8),i);
// mat3 xRot;
// rotationX(PI*.07*i,xRot);
// data.invSaberRot=data.invSaberRot*xRot;

// //foot placement
// data.footLPos=mix(data.footLPos,vec3(-.8,.1,-.6*ll),i);
// data.footLPos.y+=ll*.1*pingPong(i);

// return 1.;
// }

// float poseSaberFront(float i,inout StickmanData data)
// {
// data.saberPos=mix(data.saberPos,vec3(.2,-.4,-1.4),i);
// mat3 xRot;
// rotationX(PI*.25*i,xRot);
// data.invSaberRot=data.invSaberRot*xRot;

// //foot placement
// data.footRPos=mix(data.footRPos,vec3(.6,.1,-.8*ll),i);
// data.footRPos.y+=ll*.1*pingPong(i);
// return 0.;
// }

// float poseSaberBack(float i,inout StickmanData data)
// {
// mat3 xRot;
// rotationX(.55*PI*i,xRot);
// mat3 yRot;
// rotationY(-.07*PI*i,yRot);

// data.invSaberRot=data.invSaberRot*xRot*yRot;

// mat3 zRot;
// rotationZ(PI*.4*i,zRot);
// data.handLRot=data.handLRot*zRot;
// data.handLPos=mix(data.handLPos,vec3(-1.3,.3,-.9),i);
// data.saberPos=mix(data.saberPos,vec3(1.3,.2,.5),i);

// //foot placement
// data.footLPos=mix(data.footLPos,vec3(-.6,.1,-1.*ll),i);
// data.footLPos.y+=ll*.1*pingPong(i);
// return 0.;
// }

// float poseSaberBackDown(float i,inout StickmanData data)
// {
// mat3 xRot;
// rotationX(.65*PI*i,xRot);
// mat3 yRot;
// rotationY(.3*PI*i,yRot);

// data.invSaberRot=data.invSaberRot*xRot*yRot;

// mat3 zRot;
// rotationZ(PI*.4*i,zRot);
// data.handLRot=data.handLRot*zRot;
// data.handLPos=mix(data.handLPos,vec3(-1.2,-.3,-.8),i);

// data.saberPos=mix(data.saberPos,vec3(1.3,-.3,.5),i);

// //foot placement
// data.footLPos=mix(data.footLPos,vec3(-.7,.1,-.7*ll),i);
// data.footLPos.y+=ll*.1*pingPong(i);
// return 0.;
// }

// float animateEntranceJedi(float p,inout StickmanData data)
// {
// data.saberLen*=smoothstep(.05,.3,p);
// float pose1=1.-smoothstep(.52,.7,p);
// poseSaberFront(pose1,data);

// frontLoop(smoothstep(.3,.4,p)-smoothstep(.65,.7,p),linearstep(.3,.65,p)*2.,data);

// float pose2=smoothstep(.5,.7,p);
// poseSaberSide(pose2,data);

// return pose2;
// }

// float animateEntranceSith(float p,inout StickmanData data)
// {
// data.saberLen*=smoothstep(.05,.15,p);
// float pose1=1.-smoothstep(.52,.6,p);
// poseSaberBackDown(pose1,data);

// backLoop(max(smoothstep(.2,.25,p)-smoothstep(.55,.6,p),.00001),linearstep(.2,.55,p)*3.,data);

// float pose2=smoothstep(.5,.6,p);
// poseSaberBack(pose2,data);
// return 0.;
// }

// #define ANIMATE 1

// //assumes t is time
// //i is a float
// //data is the stickman
// //hit receives the hit progress
// //twoHanded receives the two hand amount
// #define HIT_SEQ(s,e,m,hitAnim)if(t>s&&t<=e){i=(t-s)/(e-s);hit=hitAnim(i,m,data);}
// #define HOLD_POSE(s,e,poseAnim)if(t>s&&t<=e){twoHanded=poseAnim(1.,data);}
// #define TRANS_POSE(s,e,prevPoseAnim,poseAnim)if(t>s&&t<=e){i=(t-s)/(e-s);prevTwoHanded=prevPoseAnim(1.-i,data);twoHanded=poseAnim(i,data);twoHanded=mix(prevTwoHanded,twoHanded,i);}

// float loopTime=9.5;

// void animateJedi(float t,inout StickmanData data)
// {
// float entranceDur=4.5;
// float prevTwoHanded=0.;
// float twoHanded=0.;
// float i=0.;
// float hit=0.;
// float s,e;

// #if ANIMATE
// s=-entranceDur;
// e=0.;
// TRANS_POSE(s,e,nullPose,animateEntranceJedi)

// t=mod(t,loopTime)*step(0.,t);

// s=e;
// e=s+.5;
// HOLD_POSE(s,e,poseSaberSide)

// s=e;
// e=s+.7;
// HOLD_POSE(s,e,poseSaberSide)
// HIT_SEQ(s,e,1.,parryDownLeft)

// s=e;
// e=s+.2;
// HOLD_POSE(s,e,poseSaberSide)

// s=e;
// e=s+1.65;
// HOLD_POSE(s,e,poseSaberSide)
// HIT_SEQ(s,e,.60,whirlingHit)

// s=e;
// e=s+1.;
// HOLD_POSE(s,e,poseSaberSide)

// s=e;
// e=s+.9;
// HOLD_POSE(s,e,poseSaberSide)
// HIT_SEQ(s,e,1.,parryDownLeft)

// s=e;
// e=s+.45;
// TRANS_POSE(s,e,poseSaberSide,poseSaberFront)

// s=e;
// e=s+.9;
// HOLD_POSE(s,e,poseSaberFront)
// HIT_SEQ(s,e,1.,parryDownLeft)

// s=e;
// e=s+2.;
// HOLD_POSE(s,e,poseSaberFront)
// HIT_SEQ(s,e,.4375,upDownHit)

// s=e;
// e=s+.4;
// HOLD_POSE(s,e,poseSaberFront)

// s=e;
// e=s+.6;
// TRANS_POSE(s,e,poseSaberFront,poseSaberSide)

// s=e;
// e=loopTime;
// HOLD_POSE(s,e,poseSaberSide)
// #endif

// invKinematics(twoHanded,hit,data);
// }

// void animateSith(float t,inout StickmanData data)
// {
// float entranceDur=4.5;
// float twoHanded=0.;
// float i=0.;
// float hit=0.;
// float prevTwoHanded=0.;

// float s,e;
// #if ANIMATE
// //do pose
// s=-entranceDur;
// e=0.;
// TRANS_POSE(s,e,nullPose,animateEntranceSith)

// t=mod(t,loopTime)*step(0.,t);

// s=e;
// e=s+1.7;
// HOLD_POSE(s,e,poseSaberBack)
// HIT_SEQ(s,e,.434,upDownHit)

// s=e;
// e=s+.6;
// HOLD_POSE(s,e,poseSaberBack)

// s=e;
// e=s+.6;
// HOLD_POSE(s,e,poseSaberBack)
// HIT_SEQ(s,e,1.,parryUpRight)

// s=e;
// e=s+.5;
// TRANS_POSE(s,e,poseSaberBack,poseSaberBackDown)

// s=e;
// e=s+1.5;
// HOLD_POSE(s,e,poseSaberBackDown)
// HIT_SEQ(s,e,.558,whirlingHit)

// s=e;
// e=s+.4;
// TRANS_POSE(s,e,poseSaberBackDown,poseSaberBack)

// s=e;
// e=s+1.;
// HOLD_POSE(s,e,poseSaberBack)
// HIT_SEQ(s,e,.6,forwardHit)

// s=e;
// e=s+.1;
// HOLD_POSE(s,e,poseSaberBack)

// s=e;
// e=s+.42;
// TRANS_POSE(s,e,poseSaberBack,poseSaberBackDown)

// s=e;
// e=s+1.2;
// HOLD_POSE(s,e,poseSaberBackDown)
// HIT_SEQ(s,e,1.,parryDownLeft)

// s=e;
// e=s+.8;
// HOLD_POSE(s,e,poseSaberBackDown)

// s=e;
// e=s+.5;
// TRANS_POSE(s,e,poseSaberBackDown,poseSaberBack)

// s=e;
// e=loopTime;
// HOLD_POSE(s,e,poseSaberBack)
// #endif

// invKinematics(twoHanded,hit,data);
// }

// void initStickman(inout StickmanData data,bool isJedi)
// {
// data.stickmanPos=vec3(0.,-1.,0.);
// //relative to stickManPos
// data.bodyPos=vec3(0.,1.5,0.);
// data.bodyDeform=vec3(1.,1.15,1.);
// data.headPos=vec3(0.,.05,-.92);
// data.handRPos=vec3(1.1,-.45,-.5);
// data.handLPos=vec3(-1.1,-.45,-.5);
// data.handRDeform=vec3(1.2,1.5,1.6);
// data.handLDeform=vec3(1.2,1.5,1.6);
// data.handRRot=IMAT3;
// data.handLRot=IMAT3;
// data.footRPos=vec3(.6,.1,-.1);
// data.footLPos=vec3(-.6,.1,-.1);
// data.footRRot=IMAT3;
// data.footLRot=IMAT3;
// data.footRDeform=vec3(1.5,.9,1.8);
// data.footLDeform=vec3(1.5,.9,1.8);

// data.invBodyRot=IMAT3;
// data.invStickmanRot=IMAT3;
// data.invMouthRot=IMAT3;

// //relative to headPos
// data.eyeRDeform=vec3(2.,1.8,1.);
// data.eyeLDeform=vec3(2.,2.5,1.);

// data.mouthDeform=vec3(2.,1.,3.5);

// data.saberPos=vec3(1.1,-.45,-.5);
// data.saberRadius=.06;
// data.saberLen=.85;
// data.saberNoise=isJedi?JEDI_SABER_NOISE:SITH_SABER_NOISE;
// data.invSaberRot=IMAT3;

// data.laserColor=LASER_CORE+(isJedi?JEDI:SITH);
// data.laserLight=(data.laserColor-LASER_CORE)*LASER_LIGHT_STR;

// rotationX(mouthXRot,data.invMouthRot);
// }

// vec4 characterField(vec3 p,inout float minDist)
// {
// vec4 jediField=vec4(maxDist);
// vec4 sithField=vec4(maxDist);
// float jediMinDist=MAX_DIST;
// float sithMinDist=MAX_DIST;
// jediField=fStickman(jediData.invStickmanRot*(p-jediData.stickmanPos),jediData,jediFieldData,jediMinDist);
// #ifdef TWO_EGGS
// sithField=fStickman(sithData.invStickmanRot*(p-sithData.stickmanPos),sithData,sithFieldData,sithMinDist);
// #endif
// minDist=min(jediMinDist,sithMinDist);
// return jediField*step(jediMinDist,minDist)+sithField*step(sithMinDist,minDist);
// }

// ////////////////////////////////

// //get distance to nearest surface and atmosphere/surface color
// vec4 colorDistanceField(vec3 point,inout float minDist)
// {
// float charDist=MAX_DIST;
// vec4 charfield=characterField(point,charDist);

// vec3 mPoint=point-vec3(7.5,0.,2.);
// pMod2(mPoint.xz,vec2(15.,15.));

// float hexaHeight=3.;
// float hexaDist=fHexagonCircumcircle(mPoint,vec2(1.5,hexaHeight));
// float distPlane=fPlane(plane,point);
// minDist=min(minDist,distPlane);
// minDist=min(minDist,charDist);
// minDist=min(minDist,hexaDist);

// //blend colors
// vec4 color=vec4(0.);
// color+=groundColor*step(distPlane,minDist);
// color+=groundColor*step(hexaDist,minDist);
// color+=charfield*step(charDist,minDist);

// return color;
// }

// //get distance and color to nearest surface
// float distanceField(vec3 point)
// {
// float minDist=MAX_DIST;
// colorDistanceField(point,minDist);
// return minDist;
// }

// vec3 computeNormal(vec3 p,float roughness,out float ao)
// {
// vec3 normalWS=vec3(0.);
// for(int i=min(0,u_frame);i<4;i++)
// {
// vec3 e=.5773*(2.*vec3((((i+3)>>1)&1),((i>>1)&1),(i&1))-1.);
// uint unusedMatId;
// normalWS+=e*distanceField(p+e*.001);
// }
// normalWS=normalize(normalWS);
// vec3 deform=noise3(p*.0002);

// ao=length(deform);
// deform=deform*2.-vec3(1.);
// return normalize(normalWS+deform*roughness*.0001);
// }

// vec3 computeSaberLightDir(vec3 point,StickmanData data,FieldData fieldData)
// {
// #if LIGHT_QUALITY
// float grad=.75;

// vec3 normalWS=vec3(0.);
// for(int i=min(0,u_frame);i<4;i++)
// {
// vec3 e=.5773*(2.*vec3((((i+3)>>1)&1),((i>>1)&1),(i&1))-1.);
// uint unusedMatId;
// vec3 p=point+e*grad;
// normalWS+=e*fSaber(data.invStickmanRot*(p-data.stickmanPos),data,fieldData);
// }
// normalWS=-normalize(normalWS);
// return normalWS;
// #else
// vec3 s=(vec3(0.,data.saberLen*2.,0.)*data.invSaberRot);
// vec3 a=data.stickmanPos+(data.bodyPos+data.saberPos*data.bodyDeform)*data.invStickmanRot;
// vec3 c=data.stickmanPos+(data.bodyPos+(s+data.saberPos)*data.bodyDeform)*data.invStickmanRot;
// return normalize(mix(a,c,.5)-point);
// #endif
// }

// float distBetweenSabers(StickmanData first,StickmanData secnd,FieldData secndField)
// {
// vec3 s=(vec3(0.,first.saberLen*2.,0.)*first.invSaberRot);
// vec3 a=first.stickmanPos+(first.bodyPos+first.saberPos*first.bodyDeform)*first.invStickmanRot;
// vec3 c=first.stickmanPos+(first.bodyPos+(s+first.saberPos)*first.bodyDeform)*first.invStickmanRot;

// float sithDistLaser=1000.;
// for(float i=0.;i<=1.;i+=1./32.)
// {
// vec3 b=mix(a,c,i);
// vec3 stickmanDiff=secnd.invStickmanRot*(b-secnd.stickmanPos);
// sithDistLaser=min(sithDistLaser,fSaber(stickmanDiff,secnd,secndField));
// }

// return sithDistLaser;
// }

// vec3 doLighting(vec3 surfColor,vec3 surfPoint,vec3 surfNormal,vec3 lightColor,vec3 lightDir,float roughness)
// {
// if(dot(surfColor,surfColor)<=2.5)
// {
// float lightingWrap=.5;
// float diff=dot(surfNormal,lightDir);
// diff=clamp((diff+lightingWrap)/((1.+lightingWrap)*(1.+lightingWrap)),0.,1.);
// vec3 eyeDir=normalize(projectionCenter-surfPoint);
// vec3 halfVec=normalize(eyeDir+lightDir);
// float spec=clamp(dot(halfVec,surfNormal),0.,1.);
// spec=pow(spec,mix(128.,8.,pow(roughness,.5)))*pow(diff,1.);
// surfColor=surfColor*diff*lightColor+lightColor*spec;
// }
// return surfColor;
// }

// //raymarch and sample atmosphere color along the ray
// vec4 rmAtmosphere(vec3 rayStart,vec3 rayDir,float minDist)
// {
// float cloud=0.;
// float transmittance=1.;
// vec3 scatteredLight=vec3(0.,0.,0.);

// float totalDist=minDist;
// float dist=0.;
// float dStep=0.;
// vec3 color=zero;
// float stepBias,jediDistLaser,sithDistLaser,strLaser;
// vec3 atmColor,surfColor,litColor;
// vec3 endPoint,sithStickmanDiff,jediStickmanDiff,normal;
// vec3 jediSaberLightDir,sithSaberLightDir;
// vec4 dfRes;
// float roughness=.0;
// vec3 S,Sint;
// float saberOverlap;

// float distSab=distBetweenSabers(jediData,sithData,sithFieldData);
// //distSab = min(distSab, distBetweenSabers(sithData, jediData, jediFieldData));
// float contactLightPower=1.+smoothstep(.3,.15,distSab)*3.;

// vec4 rmRes;

// for(int i=0;i<MAX_STEPS;++i)
// {
// stepBias=max(MIN_STEP_BIAS,totalDist*2./MAX_DIST);//to avoid artefacts

// endPoint=rayStart+rayDir*totalDist;
// jediStickmanDiff=jediData.invStickmanRot*(endPoint-jediData.stickmanPos);
// jediFieldData.fSaber=fSaber(jediStickmanDiff,jediData,jediFieldData);
// strLaser=1.+smoothstep(jediData.saberLen*2.,0.,fHandle(jediStickmanDiff,jediData,jediFieldData))*2.;
// jediDistLaser=(LASER_STR+strLaser)/pow(jediFieldData.fSaber,2.);

// #ifdef TWO_EGGS
// sithStickmanDiff=sithData.invStickmanRot*(endPoint-sithData.stickmanPos);
// sithFieldData.fSaber=fSaber(sithStickmanDiff,sithData,sithFieldData);
// strLaser=1.+smoothstep(sithData.saberLen*2.,0.,fHandle(sithStickmanDiff,sithData,sithFieldData))*2.;
// sithDistLaser=(LASER_STR+strLaser)/pow(sithFieldData.fSaber,2.);

// saberOverlap=1./pow(jediFieldData.fSaber*sithFieldData.fSaber,1.5);
// jediDistLaser+=saberOverlap;
// sithDistLaser+=saberOverlap;
// #endif

// jediSaberLightDir=computeSaberLightDir(endPoint,jediData,jediFieldData);
// sithSaberLightDir=computeSaberLightDir(endPoint,sithData,sithFieldData);

// #if VOL_FOG
// vec3 atmSamplePos=endPoint+rayDir*dist*(s_pixelRand-.5);
// cloud=atmThickness(atmSamplePos);

// S=jediDistLaser*jediData.laserLight*contactLightPower*
// #if VOL_SHADOW
// volumetricShadow(atmSamplePos,jediSaberLightDir)*
// #endif
// cloud*PHASE_FUNC;// incoming light
// #ifdef TWO_EGGS
// S+=sithDistLaser*sithData.laserLight*contactLightPower*
// #if VOL_SHADOW
// volumetricShadow(atmSamplePos,sithSaberLightDir)*
// #endif
// cloud*PHASE_FUNC;// incoming light
// #endif

// Sint=(S-S*exp(-cloud*dStep))/cloud;// integrate along the current step segment
// scatteredLight+=transmittance*Sint;// accumulate and also take into account the transmittance from previous steps
// // Evaluate transmittance to view independentely
// transmittance*=exp(-cloud*dStep);
// if(transmittance<.005)
// {
// break;
// }
// #endif
// dist=MAX_DIST;
// dfRes=colorDistanceField(endPoint,dist);
// dStep=dist*stepBias;
// totalDist+=dStep;

// if(dist<=MIN_DIST)
// {
// float ao=1.;
// normal=computeNormal(endPoint,roughness,ao);
// //store final hit color
// surfColor=dfRes.xyz;
// roughness=dfRes.w;

// //do lighting
// litColor=AMBIANT_LIGHT*surfColor;
// //Don't do sunlight, night time looks better
// //litColor += doLighting(surfColor, endPoint, normal, sunLightColor, normalize(sunLightPos - endPoint), roughness);

// litColor+=doLighting(surfColor,endPoint,normal,
// (jediData.laserLight*contactLightPower)*jediDistLaser*.5,
// jediSaberLightDir,roughness);
// #ifdef TWO_EGGS

// litColor+=doLighting(surfColor,endPoint,normal,
// (sithData.laserLight*contactLightPower)*sithDistLaser*.5,
// sithSaberLightDir,roughness);
// #endif

// color=surfColor*ao*.01+litColor;

// rmRes=vec4(color,totalDist);
// break;
// }

// //no surface hit, return sky + atmColor
// if(totalDist>=MAX_DIST||i>=MAX_STEPS-1)
// {
// rmRes=vec4(color+skyColor,MAX_DIST+.01);
// break;
// }
// }

// rmRes.xyz=mix(fogColor*.8,rmRes.xyz,transmittance)+scatteredLight;
// return rmRes;
// }

// void main()
// {
// s_pixelRand=texture2D(iChannel0,gl_FragCoord/vec2(1024.),0.).r;
// s_pixelRand=fract(s_pixelRand+float(u_frame%256)*1.618);
// s_time=u_time;

// vec2 mousePos=u_mouse.xy/u_resolution.xy*2.-vec2(1.);
// float day=0.;
// day=sign(day)*pow(abs(day),2.);
// dayProgress=abs(day);

// float sunsetFromNight=smoothstep(.4,.5,dayProgress);
// float sunsetToDay=smoothstep(.8,.5,dayProgress);
// vec3 sunsetColor=mix(mix(vec3(.5,0.,0.),vec3(1.,.8,.3),sunsetFromNight),
// mix(vec3(.2,.2,1.),vec3(1.,.8,.3),sunsetToDay),(sunsetFromNight+sunsetToDay)/2.);
// float sunsetStr=sunsetFromNight*sunsetToDay;

// sunLightPos=vec3(0.,-1000.,0.);
// mat3 sRotZ;
// rotationZ(day*PI,sRotZ);
// sunLightPos=sRotZ*sunLightPos;

// sunLightColor=mix(vec3(.004,.004,.0065),vec3(.8,.8,.7),dayProgress);
// sunLightColor=mix(sunLightColor,sunsetColor,sunsetStr);

// vec2 uv=gl_FragCoord.xy/u_resolution;
// vec3 ro=vec3(0.);

// float t=s_time*1.1;
// t+=(cos(t*.5))*.2;

// float camT=t*.5;
// float camRotY=(mousePos.x+camT*.1)*PI*-2.;
// float camY=(1.-cos(camT*.5))*.3;
// float camDist=12.-sin(camT*.5)*4.;

// //animate before marching
// initStickman(jediData,true);
// #ifdef TWO_EGGS
// jediData.stickmanPos.x+=2.7;
// mat3 yRot;
// rotationY(-.5*PI,yRot);
// jediData.invStickmanRot=yRot*jediData.invStickmanRot;

// initStickman(sithData,false);
// sithData.stickmanPos.x-=2.7;
// rotationY(.5*PI,yRot);
// sithData.invStickmanRot=yRot*sithData.invStickmanRot;
// animateSith(t,sithData);
// computeFieldData(sithData,sithFieldData);
// #endif
// animateJedi(t,jediData);
// computeFieldData(jediData,jediFieldData);

// //////////////////

// //Do camera setup from mouse coord
// vec3 pCenter=vec3(0.,.2,0.);
// vec3 pOffset=vec3(0.,0.,1.);

// mat3 pRotY;
// rotationY(camRotY,pRotY);
// pOffset.y=camY;
// pOffset=pRotY*pOffset;
// projectionCenter=pCenter+pOffset*camDist;

// vec3 tmpCenter=(projectionCenter+vec3(0.,0.,.50));

// projectionCenter=(projectionCenter);

// projectionForward=normalize(-pOffset);
// projectionUp=vec3(0.,1.,0.);
// projectionRight=cross(projectionUp,projectionForward);
// projectionUp=cross(projectionForward,projectionRight);
// mousePos=pixelToNormalizedspace(u_mouse.xy);

// cameraOffset=-projectionForward*FOCAL_LENGTH;

// vec2 rd=uv*2.-vec2(1.);
// rd.y/=u_resolution.x/u_resolution.y;
// //setup ray
// vec3 rayPos=projectionCenter+cameraOffset;
// vec3 pointOnProjectionPlane=projectionCenter+projectionRight*rd.x+projectionUp*rd.y;
// vec3 rayDirection=normalize(pointOnProjectionPlane-rayPos);

// float sun=pow(max(0.,dot(rayDirection,normalize(sunLightPos))),2.);

// //sky and stars
// vec2 xzDir=normalize(rayDirection.xz);
// vec2 starsUv=vec2(atan(xzDir.x,xzDir.y),rayDirection.y);
// vec3 stars=texture2D(iChannel0,starsUv*0.1,0.).xyz;
// stars*=pow(dot(stars,stars)*.5,16.)*.3;// smoothstep(2.1, 2.5, dot(stars, stars));
// stars=smoothstep(vec3(0.),vec3(1.),stars);
// float skyHeight=pow(max(0.,rayDirection.y)*2.,.75);
// float starVis=skyHeight*pow(1.-dayProgress,2.);
// stars=mix(zero,stars,pow(starVis,6.));

// vec3 lowColor=mix(vec3(.01,.01,.05),vec3(.85,.85,1.),dayProgress);
// lowColor=mix(lowColor,sunsetColor,sunsetStr+pow(sun,5.)*sunsetStr*2.);
// vec3 upColor=mix(vec3(.0005,.0005,.001),vec3(.15,.15,1.),dayProgress);
// upColor=mix(upColor,sunsetColor,sunsetStr*.5+pow(sun,5.)*sunsetStr*2.);

// skyColor=mix(lowColor,upColor,skyHeight);

// float fogBlur=.5;
// fogColor=mix(mix(lowColor,upColor,max(0.,skyHeight-fogBlur)),
// mix(lowColor,upColor,min(1.,skyHeight+fogBlur)),
// .5);

// //march ray
// vec4 rayMarchResult=rmAtmosphere(rayPos,rayDirection,0.);
// float dist=rayMarchResult.w;
// vec4 surfaceColor=vec4(rayMarchResult.xyz,1.);

// if(dist>=MAX_DIST)
// {
// surfaceColor.xyz+=stars;
// surfaceColor.xyz=surfaceColor.xyz+sunLightColor*pow(sun,80.)*10.;
// }

// //convert to gamma space
// surfaceColor=pow(surfaceColor,vec4(1./2.2));
// gl_FragColor=surfaceColor;
// }
void main(){
  float bug=0.0;
  vec3 tile=texture2D(iChannel0,gl_FragCoord.xy/u_resolution,0.).xyz;
  vec4 col=vec4(tile, 1.0);
  //if(....)
  bug=0.01;
  col.x+=bug;
  gl_FragColor=col;
}

primitives


uniform vec3 u_color;
uniform float u_frame;

uniform vec2 u_mouse;
uniform vec2 u_resolution;
//传递长和宽
uniform float u_time;
varying vec2 vUv;



#define AA 3   // make this 2 or 3 for antialiasing

//------------------------------------------------------------------
float dot2( in vec2 v ) { return dot(v,v); }
float dot2( in vec3 v ) { return dot(v,v); }
float ndot( in vec2 a, in vec2 b ) { return a.x*b.x - a.y*b.y; }

float sdPlane( vec3 p )
{
	return p.y;
}

float sdSphere( vec3 p, float s )
{
    return length(p)-s;
}

float sdBox( vec3 p, vec3 b )
{
    vec3 d = abs(p) - b;
    return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}

// float min(float x,float y){
//     #if x>y
//     return y
//     #else 
//     return x
//     #endif
// }

float sdBoxFrame( vec3 p, vec3 b, float e )
{
       p = abs(p  )-b;
  vec3 q = abs(p+e)-e;

  return min(min(
      length(max(vec3(p.x,q.y,q.z),0.0))+min(max(p.x,max(q.y,q.z)),0.0),
      length(max(vec3(q.x,p.y,q.z),0.0))+min(max(q.x,max(p.y,q.z)),0.0)),
      length(max(vec3(q.x,q.y,p.z),0.0))+min(max(q.x,max(q.y,p.z)),0.0));
}
float sdEllipsoid( in vec3 p, in vec3 r ) // approximated
{
    float k0 = length(p/r);
    float k1 = length(p/(r*r));
    return k0*(k0-1.0)/k1;
}

float sdTorus( vec3 p, vec2 t )
{
    return length( vec2(length(p.xz)-t.x,p.y) )-t.y;
}

float sdCappedTorus(in vec3 p, in vec2 sc, in float ra, in float rb)
{
    p.x = abs(p.x);
    float k = (sc.y*p.x>sc.x*p.y) ? dot(p.xy,sc) : length(p.xy);
    return sqrt( dot(p,p) + ra*ra - 2.0*ra*k ) - rb;
}

float sdHexPrism( vec3 p, vec2 h )
{
    vec3 q = abs(p);

    const vec3 k = vec3(-0.8660254, 0.5, 0.57735);
    p = abs(p);
    p.xy -= 2.0*min(dot(k.xy, p.xy), 0.0)*k.xy;
    vec2 d = vec2(
       length(p.xy - vec2(clamp(p.x, -k.z*h.x, k.z*h.x), h.x))*sign(p.y - h.x),
       p.z-h.y );
    return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}

float sdOctogonPrism( in vec3 p, in float r, float h )
{
  const vec3 k = vec3(-0.9238795325,   // sqrt(2+sqrt(2))/2 
                       0.3826834323,   // sqrt(2-sqrt(2))/2
                       0.4142135623 ); // sqrt(2)-1 
  // reflections
  p = abs(p);
  p.xy -= 2.0*min(dot(vec2( k.x,k.y),p.xy),0.0)*vec2( k.x,k.y);
  p.xy -= 2.0*min(dot(vec2(-k.x,k.y),p.xy),0.0)*vec2(-k.x,k.y);
  // polygon side
  p.xy -= vec2(clamp(p.x, -k.z*r, k.z*r), r);
  vec2 d = vec2( length(p.xy)*sign(p.y), p.z-h );
  return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}

float sdCapsule( vec3 p, vec3 a, vec3 b, float r )
{
	vec3 pa = p-a, ba = b-a;
	float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
	return length( pa - ba*h ) - r;
}

float sdRoundCone( in vec3 p, in float r1, float r2, float h )
{
    vec2 q = vec2( length(p.xz), p.y );
    
    float b = (r1-r2)/h;
    float a = sqrt(1.0-b*b);
    float k = dot(q,vec2(-b,a));
    
    if( k < 0.0 ) return length(q) - r1;
    if( k > a*h ) return length(q-vec2(0.0,h)) - r2;
        
    return dot(q, vec2(a,b) ) - r1;
}

float sdRoundCone(vec3 p, vec3 a, vec3 b, float r1, float r2)
{
    // sampling independent computations (only depend on shape)
    vec3  ba = b - a;
    float l2 = dot(ba,ba);
    float rr = r1 - r2;
    float a2 = l2 - rr*rr;
    float il2 = 1.0/l2;
    
    // sampling dependant computations
    vec3 pa = p - a;
    float y = dot(pa,ba);
    float z = y - l2;
    float x2 = dot2( pa*l2 - ba*y );
    float y2 = y*y*l2;
    float z2 = z*z*l2;

    // single square root!
    float k = sign(rr)*rr*rr*x2;
    if( sign(z)*a2*z2 > k ) return  sqrt(x2 + z2)        *il2 - r2;
    if( sign(y)*a2*y2 < k ) return  sqrt(x2 + y2)        *il2 - r1;
                            return (sqrt(x2*a2*il2)+y*rr)*il2 - r1;
}

float sdTriPrism( vec3 p, vec2 h )
{
    const float k = sqrt(3.0);
    h.x *= 0.5*k;
    p.xy /= h.x;
    p.x = abs(p.x) - 1.0;
    p.y = p.y + 1.0/k;
    if( p.x+k*p.y>0.0 ) p.xy=vec2(p.x-k*p.y,-k*p.x-p.y)/2.0;
    p.x -= clamp( p.x, -2.0, 0.0 );
    float d1 = length(p.xy)*sign(-p.y)*h.x;
    float d2 = abs(p.z)-h.y;
    return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.);
}

// vertical
float sdCylinder( vec3 p, vec2 h )
{
    vec2 d = abs(vec2(length(p.xz),p.y)) - h;
    return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}

// arbitrary orientation
float sdCylinder(vec3 p, vec3 a, vec3 b, float r)
{
    vec3 pa = p - a;
    vec3 ba = b - a;
    float baba = dot(ba,ba);
    float paba = dot(pa,ba);

    float x = length(pa*baba-ba*paba) - r*baba;
    float y = abs(paba-baba*0.5)-baba*0.5;
    float x2 = x*x;
    float y2 = y*y*baba;
    float d = (max(x,y)<0.0)?-min(x2,y2):(((x>0.0)?x2:0.0)+((y>0.0)?y2:0.0));
    return sign(d)*sqrt(abs(d))/baba;
}

// vertical
float sdCone( in vec3 p, in vec2 c, float h )
{
    vec2 q = h*vec2(c.x,-c.y)/c.y;
    vec2 w = vec2( length(p.xz), p.y );
    
	vec2 a = w - q*clamp( dot(w,q)/dot(q,q), 0.0, 1.0 );
    vec2 b = w - q*vec2( clamp( w.x/q.x, 0.0, 1.0 ), 1.0 );
    float k = sign( q.y );
    float d = min(dot( a, a ),dot(b, b));
    float s = max( k*(w.x*q.y-w.y*q.x),k*(w.y-q.y)  );
	return sqrt(d)*sign(s);
}

float sdCappedCone( in vec3 p, in float h, in float r1, in float r2 )
{
    vec2 q = vec2( length(p.xz), p.y );
    
    vec2 k1 = vec2(r2,h);
    vec2 k2 = vec2(r2-r1,2.0*h);
    vec2 ca = vec2(q.x-min(q.x,(q.y < 0.0)?r1:r2), abs(q.y)-h);
    vec2 cb = q - k1 + k2*clamp( dot(k1-q,k2)/dot2(k2), 0.0, 1.0 );
    float s = (cb.x < 0.0 && ca.y < 0.0) ? -1.0 : 1.0;
    return s*sqrt( min(dot2(ca),dot2(cb)) );
}

float sdCappedCone(vec3 p, vec3 a, vec3 b, float ra, float rb)
{
    float rba  = rb-ra;
    float baba = dot(b-a,b-a);
    float papa = dot(p-a,p-a);
    float paba = dot(p-a,b-a)/baba;

    float x = sqrt( papa - paba*paba*baba );

    float cax = max(0.0,x-((paba<0.5)?ra:rb));
    float cay = abs(paba-0.5)-0.5;

    float k = rba*rba + baba;
    float f = clamp( (rba*(x-ra)+paba*baba)/k, 0.0, 1.0 );

    float cbx = x-ra - f*rba;
    float cby = paba - f;
    
    float s = (cbx < 0.0 && cay < 0.0) ? -1.0 : 1.0;
    
    return s*sqrt( min(cax*cax + cay*cay*baba,
                       cbx*cbx + cby*cby*baba) );
}

// c is the sin/cos of the desired cone angle
float sdSolidAngle(vec3 pos, vec2 c, float ra)
{
    vec2 p = vec2( length(pos.xz), pos.y );
    float l = length(p) - ra;
	float m = length(p - c*clamp(dot(p,c),0.0,ra) );
    return max(l,m*sign(c.y*p.x-c.x*p.y));
}

float sdOctahedron(vec3 p, float s)
{
    p = abs(p);
    float m = p.x + p.y + p.z - s;

    // exact distance
    #if 0
    vec3 o = min(3.0*p - m, 0.0);
    o = max(6.0*p - m*2.0 - o*3.0 + (o.x+o.y+o.z), 0.0);
    return length(p - s*o/(o.x+o.y+o.z));
    #endif
    
    // exact distance
    #if 1
 	vec3 q;
         if( 3.0*p.x < m ) q = p.xyz;
    else if( 3.0*p.y < m ) q = p.yzx;
    else if( 3.0*p.z < m ) q = p.zxy;
    else return m*0.57735027;
    float k = clamp(0.5*(q.z-q.y+s),0.0,s); 
    return length(vec3(q.x,q.y-s+k,q.z-k)); 
    #endif
    
    // bound, not exact
    #if 0
	return m*0.57735027;
    #endif
}

float sdPyramid( in vec3 p, in float h )
{
    float m2 = h*h + 0.25;
    
    // symmetry
    p.xz = abs(p.xz);
    p.xz = (p.z>p.x) ? p.zx : p.xz;
    p.xz -= 0.5;
	
    vec3 q = vec3( p.z, h*p.y - 0.5*p.x, h*p.x + 0.5*p.y);
   
    float s = max(-q.x,0.0);
    float t = clamp( (q.y-0.5*p.z)/(m2+0.25), 0.0, 1.0 );
    
    float a = m2*(q.x+s)*(q.x+s) + q.y*q.y;
	float b = m2*(q.x+0.5*t)*(q.x+0.5*t) + (q.y-m2*t)*(q.y-m2*t);
    
    float d2 = min(q.y,-q.x*m2-q.y*0.5) > 0.0 ? 0.0 : min(a,b);
    
    // recover 3D and scale, and add sign
    return sqrt( (d2+q.z*q.z)/m2 ) * sign(max(q.z,-p.y));;
}

// la,lb=semi axis, h=height, ra=corner
float sdRhombus(vec3 p, float la, float lb, float h, float ra)
{
    p = abs(p);
    vec2 b = vec2(la,lb);
    float f = clamp( (ndot(b,b-2.0*p.xz))/dot(b,b), -1.0, 1.0 );
	vec2 q = vec2(length(p.xz-0.5*b*vec2(1.0-f,1.0+f))*sign(p.x*b.y+p.z*b.x-b.x*b.y)-ra, p.y-h);
    return min(max(q.x,q.y),0.0) + length(max(q,0.0));
}

float sdHorseshoe( in vec3 p, in vec2 c, in float r, in float le, vec2 w )
{
    p.x = abs(p.x);
    float l = length(p.xy);
    p.xy = mat2(-c.x, c.y, 
              c.y, c.x)*p.xy;
    p.xy = vec2((p.y>0.0 || p.x>0.0)?p.x:l*sign(-c.x),
                (p.x>0.0)?p.y:l );
    p.xy = vec2(p.x,abs(p.y-r))-vec2(le,0.0);
    
    vec2 q = vec2(length(max(p.xy,0.0)) + min(0.0,max(p.x,p.y)),p.z);
    vec2 d = abs(q) - w;
    return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}

float sdU( in vec3 p, in float r, in float le, vec2 w )
{
    p.x = (p.y>0.0) ? abs(p.x) : length(p.xy);
    p.x = abs(p.x-r);
    p.y = p.y - le;
    float k = max(p.x,p.y);
    vec2 q = vec2( (k<0.0) ? -k : length(max(p.xy,0.0)), abs(p.z) ) - w;
    return length(max(q,0.0)) + min(max(q.x,q.y),0.0);
}

//------------------------------------------------------------------

vec2 opU( vec2 d1, vec2 d2 )
{
	return (d1.x<d2.x) ? d1 : d2;
}

//------------------------------------------------------------------

#define ZERO 0

//------------------------------------------------------------------

vec2 map( in vec3 pos )
{
    vec2 res = vec2( pos.y, 0.0 );

    // bounding box
    if( sdBox( pos-vec3(-2.0,0.3,0.25),vec3(0.3,0.3,1.0) )<res.x )
    {
      res = opU( res, vec2( sdSphere(    pos-vec3(-2.0,0.25, 0.0), 0.25 ), 26.9 ) );
	  res = opU( res, vec2( sdRhombus(  (pos-vec3(-2.0,0.25, 1.0)).xzy, 0.15, 0.25, 0.04, 0.08 ),17.0 ) );
    }

    // bounding box
    if( sdBox( pos-vec3(0.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )
    {
	res = opU( res, vec2( sdCappedTorus((pos-vec3( 0.0,0.30, 1.0))*vec3(1,-1,1), vec2(0.866025,-0.5), 0.25, 0.05), 25.0) );
    res = opU( res, vec2( sdBoxFrame(    pos-vec3( 0.0,0.25, 0.0), vec3(0.3,0.25,0.2), 0.025 ), 16.9 ) );
	res = opU( res, vec2( sdCone(        pos-vec3( 0.0,0.45,-1.0), vec2(0.6,0.8),0.45 ), 55.0 ) );
    res = opU( res, vec2( sdCappedCone(  pos-vec3( 0.0,0.25,-2.0), 0.25, 0.25, 0.1 ), 13.67 ) );
    res = opU( res, vec2( sdSolidAngle(  pos-vec3( 0.0,0.00,-3.0), vec2(3,4)/5.0, 0.4 ), 49.13 ) );
    }

    // bounding box
    if( sdBox( pos-vec3(1.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )
    {
	res = opU( res, vec2( sdTorus(      (pos-vec3( 1.0,0.30, 1.0)).xzy, vec2(0.25,0.05) ), 7.1 ) );
    res = opU( res, vec2( sdBox(         pos-vec3( 1.0,0.25, 0.0), vec3(0.3,0.25,0.1) ), 3.0 ) );
    res = opU( res, vec2( sdCapsule(     pos-vec3( 1.0,0.00,-1.0),vec3(-0.1,0.1,-0.1), vec3(0.2,0.4,0.2), 0.1  ), 31.9 ) );
	res = opU( res, vec2( sdCylinder(    pos-vec3( 1.0,0.25,-2.0), vec2(0.15,0.25) ), 8.0 ) );
    res = opU( res, vec2( sdHexPrism(    pos-vec3( 1.0,0.2,-3.0), vec2(0.2,0.05) ), 18.4 ) );
    }

    // bounding box
    if( sdBox( pos-vec3(-1.0,0.35,-1.0),vec3(0.35,0.35,2.5))<res.x )
    {
	res = opU( res, vec2( sdPyramid(    pos-vec3(-1.0,-0.6,-3.0), 1.0 ), 13.56 ) );
	res = opU( res, vec2( sdOctahedron( pos-vec3(-1.0,0.15,-2.0), 0.35 ), 23.56 ) );
    res = opU( res, vec2( sdTriPrism(   pos-vec3(-1.0,0.15,-1.0), vec2(0.3,0.05) ),43.5 ) );
    res = opU( res, vec2( sdEllipsoid(  pos-vec3(-1.0,0.25, 0.0), vec3(0.2, 0.25, 0.05) ), 43.17 ) );
    res = opU( res, vec2( sdHorseshoe(  pos-vec3(-1.0,0.25, 1.0), vec2(cos(1.3),sin(1.3)), 0.2, 0.3, vec2(0.03,0.08) ), 11.5 ) );
    }

    // bounding box
    if( sdBox( pos-vec3(2.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )
    {
    res = opU( res, vec2( sdOctogonPrism(pos-vec3( 2.0,0.2,-3.0), 0.2, 0.05), 51.8 ) );
    res = opU( res, vec2( sdCylinder(    pos-vec3( 2.0,0.14,-2.0), vec3(0.1,-0.1,0.0), vec3(-0.2,0.35,0.1), 0.08), 31.2 ) );
	res = opU( res, vec2( sdCappedCone(  pos-vec3( 2.0,0.09,-1.0), vec3(0.1,0.0,0.0), vec3(-0.2,0.40,0.1), 0.15, 0.05), 46.1 ) );
    res = opU( res, vec2( sdRoundCone(   pos-vec3( 2.0,0.15, 0.0), vec3(0.1,0.0,0.0), vec3(-0.1,0.35,0.1), 0.15, 0.05), 51.7 ) );
    res = opU( res, vec2( sdRoundCone(   pos-vec3( 2.0,0.20, 1.0), 0.2, 0.1, 0.3 ), 37.0 ) );
    }
    
    return res;
}

vec2 iBox( in vec3 ro, in vec3 rd, in vec3 rad ) 
{
    vec3 m = 1.0/rd;
    vec3 n = m*ro;
    vec3 k = abs(m)*rad;
    vec3 t1 = -n - k;
    vec3 t2 = -n + k;
	return vec2( max( max( t1.x, t1.y ), t1.z ),
	             min( min( t2.x, t2.y ), t2.z ) );
}

vec2 raycast( in vec3 ro, in vec3 rd )
{
    vec2 res = vec2(-1.0,-1.0);

    float tmin = 1.0;
    float tmax = 20.0;

    // raytrace floor plane
    float tp1 = (0.0-ro.y)/rd.y;
    if( tp1>0.0 )
    {
        tmax = min( tmax, tp1 );
        res = vec2( tp1, 1.0 );
    }
    //else return res;
    
    // raymarch primitives   
    vec2 tb = iBox( ro-vec3(0.0,0.4,-0.5), rd, vec3(2.5,0.41,3.0) );
    if( tb.x<tb.y && tb.y>0.0 && tb.x<tmax)
    {
        //return vec2(tb.x,2.0);
        tmin = max(tb.x,tmin);
        tmax = min(tb.y,tmax);

        float t = tmin;
        for( int i=0; i<70 && t<tmax; i++ )
        {
            vec2 h = map( ro+rd*t );
            if( abs(h.x)<(0.0001*t) )
            { 
                res = vec2(t,h.y); 
                break;
            }
            t += h.x;
        }
    }
    
    return res;
}

// https://iquilezles.org/articles/rmshadows
float calcSoftshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax )
{
    // bounding volume
    float tp = (0.8-ro.y)/rd.y; if( tp>0.0 ) tmax = min( tmax, tp );

    float res = 1.0;
    float t = mint;
    for( int i=ZERO; i<24; i++ )
    {
		float h = map( ro + rd*t ).x;
        float s = clamp(8.0*h/t,0.0,1.0);
        res = min( res, s );
        t += clamp( h, 0.01, 0.2 );
        if( res<0.004 || t>tmax ) break;
    }
    res = clamp( res, 0.0, 1.0 );
    return res*res*(3.0-2.0*res);
}

vec3 calcNormal( in vec3 pos )
{
#if 0
    vec2 e = vec2(1.0,-1.0)*0.5773*0.0005;
    return normalize( e.xyy*map( pos + e.xyy ).x + 
					  e.yyx*map( pos + e.yyx ).x + 
					  e.yxy*map( pos + e.yxy ).x + 
					  e.xxx*map( pos + e.xxx ).x );
#else
    // inspired by tdhooper and klems - a way to prevent the compiler from inlining map() 4 times
    vec3 n = vec3(0.0);
    for( int i=ZERO; i<4; i++ )
    {
        vec3 e = 0.5773*(2.0*vec3((((i+3)>>1)&1),((i>>1)&1),(i&1))-1.0);
        n += e*map(pos+0.0005*e).x;
      //if( n.x+n.y+n.z>100.0 ) break;
    }
    return normalize(n);
#endif    
}

float calcAO( in vec3 pos, in vec3 nor )
{
	float occ = 0.0;
    float sca = 1.0;
    for( int i=ZERO; i<5; i++ )
    {
        float h = 0.01 + 0.12*float(i)/4.0;
        float d = map( pos + h*nor ).x;
        occ += (h-d)*sca;
        sca *= 0.95;
        if( occ>0.35 ) break;
    }
    return clamp( 1.0 - 3.0*occ, 0.0, 1.0 ) * (0.5+0.5*nor.y);
}

float checkersGradBox( in vec2 p, in vec2 dpdx, in vec2 dpdy )
{
    // filter kernel
    vec2 w = abs(dpdx)+abs(dpdy) + 0.001;
    // analytical integral (box filter)
    vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w;
    // xor pattern
    return 0.5 - 0.5*i.x*i.y;                  
}

vec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy )
{ 
    // background
    vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;
    
    // raycast scene
    vec2 res = raycast(ro,rd);
    float t = res.x;
	float m = res.y;
    if( m>-0.5 )
    {
        vec3 pos = ro + t*rd;
        vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos );
        vec3 ref = reflect( rd, nor );
        
        // material        
        col = 0.2 + 0.2*sin( m*2.0 + vec3(0.0,1.0,2.0) );
        float ks = 1.0;
        
        if( m<1.5 )
        {
            // project pixel footprint into the plane
            vec3 dpdx = ro.y*(rd/rd.y-rdx/rdx.y);
            vec3 dpdy = ro.y*(rd/rd.y-rdy/rdy.y);

            float f = checkersGradBox( 3.0*pos.xz, 3.0*dpdx.xz, 3.0*dpdy.xz );
            col = 0.15 + f*vec3(0.05);
            ks = 0.4;
        }

        // lighting
        float occ = calcAO( pos, nor );
        
		vec3 lin = vec3(0.0);

        // sun
        {
            vec3  lig = normalize( vec3(-0.5, 0.4, -0.6) );
            vec3  hal = normalize( lig-rd );
            float dif = clamp( dot( nor, lig ), 0.0, 1.0 );
          //if( dif>0.0001 )
        	      dif *= calcSoftshadow( pos, lig, 0.02, 2.5 );
			float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0);
                  spe *= dif;
                  spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0);
                //spe *= 0.04+0.96*pow(clamp(1.0-sqrt(0.5*(1.0-dot(rd,lig))),0.0,1.0),5.0);
            lin += col*2.20*dif*vec3(1.30,1.00,0.70);
            lin +=     5.00*spe*vec3(1.30,1.00,0.70)*ks;
        }
        // sky
        {
            float dif = sqrt(clamp( 0.5+0.5*nor.y, 0.0, 1.0 ));
                  dif *= occ;
            float spe = smoothstep( -0.2, 0.2, ref.y );
                  spe *= dif;
                  spe *= 0.04+0.96*pow(clamp(1.0+dot(nor,rd),0.0,1.0), 5.0 );
          //if( spe>0.001 )
                  spe *= calcSoftshadow( pos, ref, 0.02, 2.5 );
            lin += col*0.60*dif*vec3(0.40,0.60,1.15);
            lin +=     2.00*spe*vec3(0.40,0.60,1.30)*ks;
        }
        // back
        {
        	float dif = clamp( dot( nor, normalize(vec3(0.5,0.0,0.6))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0);
                  dif *= occ;
        	lin += col*0.55*dif*vec3(0.25,0.25,0.25);
        }
        // sss
        {
            float dif = pow(clamp(1.0+dot(nor,rd),0.0,1.0),2.0);
                  dif *= occ;
        	lin += col*0.25*dif*vec3(1.00,1.00,1.00);
        }
        
		col = lin;

        col = mix( col, vec3(0.7,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) );
    }

	return vec3( clamp(col,0.0,1.0) );
}

mat3 setCamera( in vec3 ro, in vec3 ta, float cr )
{
	vec3 cw = normalize(ta-ro);
	vec3 cp = vec3(sin(cr), cos(cr),0.0);
	vec3 cu = normalize( cross(cw,cp) );
	vec3 cv =          ( cross(cu,cw) );
    return mat3( cu, cv, cw );
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 mo = u_mouse.xy/u_resolution.xy;
	float time = 32.0 + u_time*1.5;

    // camera	
    vec3 ta = vec3( 0.25, -0.75, -0.75 );
    vec3 ro = ta + vec3( 4.5*cos(0.1*time + 7.0*mo.x), 2.2, 4.5*sin(0.1*time + 7.0*mo.x) );
    // camera-to-world transformation
    mat3 ca = setCamera( ro, ta, 0.0 );

    vec3 tot = vec3(0.0);
    for( int m=ZERO; m<AA; m++ )
    for( int n=ZERO; n<AA; n++ )
    {
        // pixel coordinates
        vec2 o = vec2(float(m),float(n)) / float(AA) - 0.5;
        vec2 p = (2.0*(fragCoord+o)-u_resolution.xy)/u_resolution.y;


        // focal length
        const float fl = 2.5;
        
        // ray direction
        vec3 rd = ca * normalize( vec3(p,fl) );

         // ray differentials
        vec2 px = (2.0*(fragCoord+vec2(1.0,0.0))-u_resolution.xy)/u_resolution.y;
        vec2 py = (2.0*(fragCoord+vec2(0.0,1.0))-u_resolution.xy)/u_resolution.y;
        vec3 rdx = ca * normalize( vec3(px,fl) );
        vec3 rdy = ca * normalize( vec3(py,fl) );
        
        // render	
        vec3 col = render( ro, rd, rdx, rdy );

        // gain
        // col = col*3.0/(2.5+col);
        
		// gamma
        col = pow( col, vec3(0.4545) );

        tot += col;
#if AA>1
    }
    tot /= float(AA*AA);
#endif
    
    fragColor = vec4( tot, 1.0 );
}

void main(){
    mainImage(gl_FragColor,vUv * u_resolution.xy);
}

simpleTruchetPattern


varying vec3 v_position;
varying vec2 vUv;
uniform float u_time;
uniform vec2 u_resolution;
uniform float u_frame;

#define HPI 1.57079632679
#define tiles 10.0

float hash21(in vec2 st)
{
    //fract(x) 获取x的小数部分
    //dot(x,y)返回x,y的点积
    //两个向量a = [a1, a2,…, an]和b = [b1, b2,…, bn]的点积定义为:
    // a·b=a1b1+a2b2+……+anbn。  
    return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.5453123);
}

float sdfTile(in vec2 p,float r , float t, int rot)
{
    p -= 0.5;
    //mat2 2*2 浮点矩阵
    p *= mat2(cos(float(rot)*HPI),-sin(float(rot)*HPI),sin(float(rot)*HPI),cos(float(rot)*HPI));
    p += 0.5;
    return abs(min(length(p),length(p - vec2(1.0)))-r)-t;
}

vec2 stepPoint(vec2 p , float c)
{
    return vec2(floor(p.x * c)/c,floor(p.y * c)/c);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord/u_resolution.xy;
    uv-=0.5;
    uv.x*=u_resolution.x/u_resolution.y;
    uv+=0.5;
    uv.x+= u_time*0.1;
    float px = tiles/u_resolution.y;
    vec2 titleUv = fract(uv*tiles);
    float tile = hash21(stepPoint(uv,tiles));
    float col = smoothstep(0.0,px,sdfTile(titleUv,0.5,0.05,int(round(tile))) );
    fragColor = vec4(vec3(col),1.0);
}

void main(){
    mainImage(gl_FragColor,vUv * u_resolution.xy);
}

wavePrint

varying vec3 v_position;
uniform float u_time;
uniform vec2 u_resolution;

void main(){
    vec2 uv = gl_FragCoord.xy/u_resolution;
    vec3 col = 0.5 + 0.5*cos(u_time+uv.xyx+vec3(0,2,4));
    float cd = 40.0;
    float lw = 500.0;
    float a = sin(u_time/20.0)*1.0;
    float r = ceil(uv.x*cd)+ceil(uv.y*cd);
    vec3 col2 = vec3( sin( ((uv.x*lw*sin(r*a))+(uv.y*lw*cos(r*a)))) );
    gl_FragColor = vec4(ceil((0.3-col.rrr-col2)),1.0);
}