Last active
October 1, 2018 20:03
-
-
Save mrange/90863c3412cfc1cb6c538ceaba8558e7 to your computer and use it in GitHub Desktop.
devchatter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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