Skip to content

Instantly share code, notes, and snippets.

@mrange
Last active October 1, 2018 20:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrange/90863c3412cfc1cb6c538ceaba8558e7 to your computer and use it in GitHub Desktop.
Save mrange/90863c3412cfc1cb6c538ceaba8558e7 to your computer and use it in GitHub Desktop.
devchatter
// For DevChatter
// License: CC0 - https://creativecommons.org/share-your-work/public-domain/cc0/
#define TOLERANCE 0.0001
#define MAX_RAY_LENGTH 16.0
#define MAX_BOUNCES 4
#define MAX_RAY_MARCHES 48
#define PI 3.141592654
#define TAU (2.0*PI)
#define DEG2RAD (PI/180.0)
#define PERIOD 12.0
#define FADETIME 2.0
#define AA 1
void pR(inout vec2 p, float a)
{
p = cos(a)*p + sin(a)*vec2(p.y, -p.x);
}
float getTimeInPeriod()
{
// return mod(iTime/10.0, PERIOD) + 3.0;
return mod(iTime, PERIOD);
}
float getPeriod()
{
return floor(iTime / PERIOD);
}
float maxComp(in vec3 p)
{
return max(p.x,max(p.y,p.z));
}
float lengthN(in vec3 v, in float n)
{
v = abs(v);
v = pow(v, vec3(n));
return pow(v.x + v.y + v.z, 1.0/n);
}
float sdRoundCube(in vec3 p, float r)
{
return lengthN(p, 8.0) - r;
}
float sgn(float x)
{
return (x<0.0)?-1.0:1.0;
}
void pR90(inout vec2 p)
{
p = vec2(p.y, -p.x);
}
void pR270(inout vec2 p)
{
p = vec2(-p.y, p.x);
}
float sdCapsule(vec3 p, in vec2 h)
{
pR90(p.xy);
float r = h.x;
float c = h.y/2.0;
return mix(length(p.xz) - r, length(vec3(p.x, abs(p.y) - c, p.z)) - r, step(c, abs(p.y)));
}
float capsule(in vec3 p, in vec2 f, in vec2 t, float r)
{
vec2 diff = t - f;
float a = atan(diff.y, diff.x);
p.xy -= f + diff*0.5;
pR(p.xy, a);
return sdCapsule(p, vec2(r, length(diff)));
}
const float logos = 1.0/350.0;
float logor(in vec3 p, float rad)
{
float r = capsule(p, vec2(0.0, 0.0), vec2(228.0, 000.0), rad);
r = min(r, capsule(p, vec2(228.0, 0.0), vec2(228.0 + 140.0, -100.0), rad));
r = min(r, capsule(p, vec2(228.0 + 140.0, -100.0), vec2(228.0 + 140.0 + 150.0, -100.0), rad));
return r;
}
float logob(in vec3 p, float rad)
{
float b = capsule(p, vec2(36.0, -36.0 - 9.0), vec2(36.0, -100.0), rad);
b = min(b, capsule(p, vec2(36.0, -100.0), vec2(228.0, -100.0), rad));
b = min(b, capsule(p, vec2(228.0, -100.0), vec2(228.0 + 140.0, 0.0), rad));
b = min(b, capsule(p, vec2(228.0 + 140.0, 0.0), vec2(228.0 + 140.0 + 150.0, 0.0), rad));
return b;
}
float ilogo(in vec3 p)
{
p /= logos;
p -= vec3(-250.0, 350.0, 40.0);
pR270(p.zy);
float r = logor(p, 28.0);
float b = logob(p, 28.0);
float d = min(r, b);
return d*logos;
}
float linstep(in float f, in float t, in float x)
{
return clamp((x - f)/(t - f), 0.0, 1.0);
}
vec3 logorcolor()
{
float time = getTimeInPeriod();
float lt = time - 3.0;
return mix(
mix(15.0*vec3(1.0, 3.0, 5.0), -3.0*vec3(5.0), linstep(0.0, 0.25, lt)),
10.0*vec3(-1.0/3.0, 3.0, 5.0),
linstep(1.5, 8.0, lt));
}
vec3 logorradiance()
{
float time = getTimeInPeriod();
float lt = time - 3.0;
return mix(
mix(vec3(0.0, 0.0, 0.0), vec3(0.4, 0.2, 0.1), linstep(0.125, 0.5, lt)),
vec3(0.1, 0.0, 0.0),
linstep(1.5, 4.0, lt));
}
float logo(in vec3 p, out vec3 col, out float ref, out float trans, out vec3 absorb)
{
p /= logos;
p -= vec3(-250.0, 350.0, 40.0);
pR270(p.zy);
float r = logor(p, 18.0);
float b = logob(p, 18.0);
b = max(b, -capsule(p, vec2(228.0, 0.0), vec2(228.0 + 140.0, -100.0), 36.0));
float d = min(r, b);
if (d == r)
{
ref = 0.4;
trans = 0.8;
col = vec3(1.0);
absorb = logorcolor();
}
else
{
ref = 0.4;
trans = 0.8;
col = vec3(1.0);
absorb = 7.0*vec3(1.0);
}
return d*logos;
}
float logor(in vec3 p)
{
p /= logos;
p -= vec3(-250.0, 350.0, 40.0);
pR270(p.zy);
return logor(p, 18.0)*logos;
}
float distanceField(in vec3 p, out vec3 col, out float ref, out float trans, out vec3 absorb)
{
float rc = sdRoundCube(p, 1.0);
float l = logo(p, col, ref, trans, absorb);
float il = ilogo(p);
int mat = 0;
float d = rc;
d = max(rc, -il);
if (d == -il) mat = 1;
d = min(d, l);
if (d == l) mat = 2;
if (mat == 0)
{
ref = 0.4;
trans = 0.0;
col = vec3(1.0);
}
else if (mat == 1)
{
ref = 0.05;
trans = 0.0;
col = vec3(1.0);
}
else
{
// Keep whatever we got
}
return d;
}
vec3 saturate(in vec3 a) { return clamp(a, 0.0, 1.0); }
vec2 saturate(in vec2 a) { return clamp(a, 0.0, 1.0); }
float saturate(in float a) { return clamp(a, 0.0, 1.0); }
const vec3 lightPos1 = 100.0*vec3(-0.3, 0.15, 1.0);
const vec3 lightPos2 = 100.0*vec3(-1.0, -0.20, -3.0);
const vec3 lightCol1 = vec3(8.0/8.0,7.0/8.0,6.0/8.0);
const vec3 lightCol2 = vec3(8.0/8.0,6.0/8.0,7.0/8.0);
vec3 getSkyColor(vec3 rayDir)
{
pR(rayDir.zy, 1.2);
vec3 lightDir1 = normalize(lightPos1);
vec3 lightDir2 = normalize(lightPos2);
float ld1 = max(dot(lightDir1, rayDir), 0.0);
float ld2 = max(dot(lightDir2, rayDir), 0.0);
vec3 final = vec3(0.125);
if ((rayDir.y > abs(rayDir.x)*1.0) && (rayDir.y > abs(rayDir.z*0.25))) final = vec3(2.0)*rayDir.y;
float roundBox = length(max(abs(rayDir.xz/max(0.0,rayDir.y))-vec2(0.9, 4.0),0.0))-0.1;
final += vec3(0.8)* pow(saturate(1.0 - roundBox*0.5), 6.0);
final += pow(lightCol1, vec3(2.0, 1.5, 1.5)) * pow(ld1, 8.0);
final += lightCol1 * pow(ld1, 200.0);
final += pow(lightCol2, vec3(2.0, 1.5, 1.5)) * pow(ld2, 1.0);
final += lightCol2 * pow(ld2, 200.0);
return final;
}
vec3 normal(in vec3 pos)
{
vec3 eps = vec3(.001,0.0,0.0);
vec3 col;
float ref;
float trans;
vec3 nor;
vec3 absorb;
nor.x = distanceField(pos+eps.xyy, col, ref, trans, absorb) - distanceField(pos-eps.xyy, col, ref, trans, absorb);
nor.y = distanceField(pos+eps.yxy, col, ref, trans, absorb) - distanceField(pos-eps.yxy, col, ref, trans, absorb);
nor.z = distanceField(pos+eps.yyx, col, ref, trans, absorb) - distanceField(pos-eps.yyx, col, ref, trans, absorb);
return normalize(nor);
}
float rayMarch(in float dmod, in vec3 ro, inout vec3 rd, float mint, float maxt, out int rep, out vec3 col, out float ref, out float trans, out vec3 absorb)
{
float t = mint;
for (int i = 0; i < MAX_RAY_MARCHES; i++)
{
float distance_ = distanceField(ro + rd*t, col, ref, trans, absorb);
float distance = dmod*distance_;
if (distance < TOLERANCE || t > maxt) break;
t += max(distance, 0.001);
rep = i;
}
return t;
}
float softShadow(in vec3 pos, in vec3 ld, in float ll, float mint, float k)
{
const float minShadow = 0.25;
float res = 1.0;
float t = mint;
vec3 col;
float ref;
float trans;
vec3 absorb;
for (int i=0; i<24; i++)
{
float distance = distanceField(pos + ld*t, col, ref, trans, absorb);
res = min(res, k*distance/t);
if (ll <= t) break;
if(res <= minShadow) break;
t += max(mint*0.2, distance);
}
return clamp(res,minShadow,1.0);
}
vec3 postProcess(in vec3 col, in vec2 q)
{
//col = saturate(col);
col=pow(clamp(col,0.0,1.0),vec3(0.75));
col=col*0.6+0.4*col*col*(3.0-2.0*col); // contrast
col=mix(col, vec3(dot(col, vec3(0.33))), -0.4); // satuation
col*=0.5+0.5*pow(19.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.7); // vigneting
return col;
}
vec3 render(in vec3 ro, in vec3 rd)
{
vec3 lightPos = 1.4*vec3(1.0, 2.5, 2.0);
vec3 final = vec3(0.0);
vec3 ragg = vec3(1.0);
float tdist = 0.0;
const float refraction = 0.9;
bool inside = false;
for (int i = 0; i < MAX_BOUNCES; ++i)
{
if (maxComp(ragg) < 0.01) break;
float dmod = inside ? -1.0 : 1.0;
vec3 absorb = vec3(3.0, 2.0, 1.0);
vec3 col = vec3(1.0);
float ref = 0.2;
float trans = 0.9;
int rep = 0;
float t = rayMarch(dmod, ro, rd, 0.01, MAX_RAY_LENGTH, rep, col, ref, trans, absorb);
tdist += t;
vec3 pos = ro + t*rd;
vec3 nor = vec3(0.0, 1.0, 0.0);
if (t < MAX_RAY_LENGTH)
{
// Ray intersected object
nor = normal(pos);
}
else
{
// Ray intersected sky
final += ragg*getSkyColor(rd);
break;
}
float mref = refraction;
if (inside)
{
nor = -nor;
mref = 1.0/refraction;
}
vec3 refl = reflect(rd, nor);
vec3 refr = refract(rd, nor, mref);
vec3 lv = lightPos - pos;
vec3 ld = normalize(lv);
float ll = length(lv);
// TODO: Rework shadow to "work" with transparent objects
float sha = 1.0;
if (!inside)
{
sha = softShadow(pos, ld, ll, 0.01, 64.0);
}
float dif = max(dot(nor,ld),0.0);
float occ = 1.0 - float(rep)/float(MAX_RAY_MARCHES);
float l = dif*occ*sha;
vec3 lr = vec3(0.0);
float dr = logor(pos);
if (!inside && dr > TOLERANCE)
{
lr = logorradiance() / (8.0*dr);
}
float lin = mix(0.2, 1.0, l);
vec3 sky = getSkyColor(refl);
col *= (0.7 + 0.3*abs(nor.zxy));
vec3 mcol = mix(lin*col + lr, sky, ref);
vec3 beer = vec3(1.0);
if (inside)
{
beer = exp(-absorb*t);
}
final += (1.0 - trans)*ragg*beer*mcol;
ragg *= trans*beer;
ro = pos;
if (refr == vec3(0.0))
{
rd = refl;
}
else
{
rd = refr;
}
if (dot(refl, rd) < 0.9)
{
inside = !inside;
}
}
return final;
}
vec3 getSample(in vec2 p)
{
// camera
float time = getTimeInPeriod();
vec3 rob = vec3(-0.05, 1.0, -0.1);
vec3 ro = (0.65 + time/16.0)*2.0*rob;
vec3 la = rob;
pR(ro.xz, -time/32.0);
vec3 ww = normalize(la - ro);
vec3 uu = normalize(cross(vec3(0.0,1.0,0.0), ww ));
vec3 vv = normalize(cross(ww,uu));
vec3 rd = normalize( p.x*uu + p.y*vv + 2.0*ww );
vec3 col = render(ro, rd);
return col;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
float time = getTimeInPeriod();
vec2 q=fragCoord.xy/iResolution.xy;
vec2 p = -1.0 + 2.0*q;
p.x *= iResolution.x/iResolution.y;
#if AA == 0
vec3 col = getSample(p);
#elif AA == 1
vec3 col = vec3(0.0);
vec2 unit = 1.0/iResolution.xy;
for(int y = 0; y < 2; ++y)
{
for(int x = 0; x < 2; ++x)
{
col += getSample(p - 0.5*unit + unit*vec2(x, y));
}
}
col /= 4.0;
#endif
float fadeIn = smoothstep(0.0, FADETIME, time);
float fadeOut = smoothstep(PERIOD - FADETIME, PERIOD, time);
fragColor = vec4(mix(postProcess(col, q)*fadeIn, vec3(1.0), fadeOut), 1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment