这里只展开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);
}