Skip to content

Instantly share code, notes, and snippets.

@mrange
Last active August 28, 2018 07:36
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/7c6c4fcfa0202a5da0c1119a271a4de9 to your computer and use it in GitHub Desktop.
Save mrange/7c6c4fcfa0202a5da0c1119a271a4de9 to your computer and use it in GitHub Desktop.
nnug
// Based of https://www.shadertoy.com/view/4sX3Rn
// Raymarching explained: http://9bitscience.blogspot.com/2013/07/raymarching-distance-fields_14.html
// Distance Estimators: www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
#define TOLERANCE 0.001
#define MAX_RAY_LENGTH 32.0
#define FADE_RAY_LENGTH 16.0
#define MAX_RAY_MARCHES 128
#define PI 3.141592654
#define TAU (2.0*PI)
float maxComp(in vec3 p)
{
return max(p.x,max(p.y,p.z));
}
float maxcomp(in vec2 p)
{
return max(p.x, p.y);
}
void rot(inout vec2 v, float a)
{
float c = cos(a);
float s = sin(a);
v.xy = vec2(v.x*c + v.y*s, -v.x*s + v.y*c);
}
float smin(float a, float b, float k)
{
float res = exp( -k*a ) + exp( -k*b );
return -log( res )/k;
}
float sdSphere(in vec3 p, in float r)
{
return length(p) - r;
}
float sdBox(vec3 p, vec3 b)
{
vec3 di = abs(p) - b;
float mc = maxComp(di);
return min(mc,length(max(di,0.0)));
}
float demo0(in vec3 p)
{
float s = sdSphere(p - vec3(0.0, 1.0, 0.0), 1.0);
return s;
}
float sdCross(in vec3 p, in float r)
{
float da = maxcomp(abs(p.xy));
float db = maxcomp(abs(p.yz));
float dc = maxcomp(abs(p.zx));
return min(da,min(db,dc)) - r;
}
float sdRepeatedCross(in vec3 p, in float r)
{
p -= r;
p = mod(p, 2.0*r) - r;
return sdCross(p, r/3.0);
}
float mengercube(in vec3 p)
{
float b = sdBox(p, vec3(1.0));
float c = sdRepeatedCross(p, 1.0);
float s = 1.0;
for(int i = 1; i < 5; ++i)
{
s /= 3.0;
c = min(c, sdRepeatedCross(p, s));
}
return max(b, -c);
}
float demo1(in vec3 p)
{
float s = 1.0/1.0;
return mengercube((p - vec3(0.0, 1.0, 0.0))/s)*s;
}
float mengercube2(in vec3 p)
{
vec3 offs = vec3(9.0);
const float s = 3.;
float d = 1e5;
float amp = 1./s;
for(int i=0; i<5; i++){
p = abs(p);
p.xy += step(p.x, p.y)*(p.yx - p.xy);
p.xz += step(p.x, p.z)*(p.zx - p.xz);
p.yz += step(p.y, p.z)*(p.zy - p.yz);
p = p*s + offs*(1. - s);
p.z -= step(p.z, offs.z*(1. - s)*.5)*offs.z*(1. - s);
rot(p.yz, 0.25*sin(iTime/4.0));
rot(p.xz, 0.25*sin(iTime/5.0));
p = abs(p);
d = min(d, max(max(p.x, p.y), p.z)*amp);
amp /= s;
}
return d - 0.038;
}
float demo2(in vec3 p)
{
float s = 1.0/9.0;
return mengercube2((p - vec3(0.0, 1.0, 0.0))/s)*s;
}
void sphere_fold(inout vec3 z, inout float dz)
{
float t = 0.0;
float fixed_radius2 = 1.9 + sin(t);
float min_radius2 = 0.1;
float r2 = dot(z, z);
if(r2 < min_radius2)
{
float temp = (fixed_radius2 / min_radius2);
z *= temp;
dz *= temp;
}
else if(r2 < fixed_radius2)
{
float temp = (fixed_radius2 / r2);
z *= temp;
dz *= temp;
}
}
void box_fold(inout vec3 z, inout float dz)
{
float folding_limit = 1.0;
z = clamp(z, -folding_limit, folding_limit) * 2.0 - z;
}
float mandelbox(vec3 z)
{
float scale = -2.8;
vec3 mtl = vec3(1.0, 1.3, 1.23)*0.8;
vec3 offset = z;
float dr = 1.0;
for(int n = 0; n < 15; ++n)
{
box_fold(z, dr);
sphere_fold(z, dr);
z = scale * z + offset;
dr = dr * abs(scale) + 1.0;
}
float r = length(z);
return r / abs(dr);
}
float demo3(in vec3 p)
{
float s = 1.0/1.5;
return mandelbox((p - vec3(0.0, 1.0, 0.0))/s)*s;
}
float mandelbulb(in vec3 p)
{
vec3 w = p;
float m = dot(w,w);
vec4 trap = vec4(abs(w),m);
float dz = 1.0;
float t = 0.0;
for(int i=0; i<4; i++)
{
dz = 8.0*pow(sqrt(m),7.0)*dz + 1.0;
float r = length(w);
float b = 8.0*acos(w.y/r);
float a = 8.0*atan(w.x, w.z);
vec3 v = vec3(sin(b)*sin(a), cos(b), sin(b)*cos(a));
rot(v.xy, t/2.0);
rot(v.yz, t/3.0);
w = p + pow(r,8.0)*v;
trap = min(trap, vec4(abs(w),m));
m = dot(w,w);
if(m > 256.0)
break;
}
return 0.25*log(m)*sqrt(m)/dz;
}
float demo4(in vec3 p)
{
float s = 1.5/1.0;
return mandelbulb((p - vec3(0.0, 1.0, 0.0))/s)*s;
}
float lengthN(in vec3 v, in float n)
{
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 demo5(in vec3 p)
{
float t = iTime;
p -= vec3(0.0, 0.5, 0.0);
vec3 bp = p;
rot(bp.xz, t / 2.0);
rot(bp.xy, t / 3.0);
rot(bp.yz, t / 5.0);
float d = sdRoundCube(bp, 0.5);
float c = 3.0;
for(float i = 0.0; i < c; ++i)
{
vec3 s = vec3(1.2 + 0.5*sin(t + i*TAU/c), 0.0, 0.0);
rot(s.xz, i*TAU/c + 1.0);
d = smin(d, sdSphere(p - s, 0.5), 10.0);
}
vec3 s = vec3(0.0, 1.2 + 0.4*sin(t*0.8), 0.0);
d = smin(d, sdSphere(p - s, 0.5), 10.0);
return d;
}
float distanceEstimator(in vec3 p)
{
return demo5(p);
}
float rayMarch(in vec3 ro, in vec3 rd)
{
float t = 0.0;
for (int i = 0; i < MAX_RAY_MARCHES; i++)
{
float distance = distanceEstimator(ro + rd*t);
if (distance < TOLERANCE || t > MAX_RAY_LENGTH) break;
t += distance;
}
return t;
}
vec3 normal(in vec3 pos)
{
vec3 eps = vec3(.001,0.0,0.0);
vec3 nor;
nor.x = distanceEstimator(pos+eps.xyy) - distanceEstimator(pos-eps.xyy);
nor.y = distanceEstimator(pos+eps.yxy) - distanceEstimator(pos-eps.yxy);
nor.z = distanceEstimator(pos+eps.yyx) - distanceEstimator(pos-eps.yyx);
return normalize(nor);
}
float ambientOcclusion(vec3 p, vec3 n)
{
float stepSize = 0.01;
float t = stepSize;
float oc = 0.0;
for(int i = 0; i < 10; i++)
{
float d = distanceEstimator(p + n * t);
oc += t - d; // Actual distance to surface - distance field value
t += stepSize;
}
return clamp(oc, 0.0, 1.0);
}
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;
for (int i=0; i<24; i++)
{
float distance = distanceEstimator(pos + ld*t);
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);
}
float specular(in vec3 nor, in vec3 ld, in vec3 rd)
{
return pow(max(dot(reflect(-ld, nor), -rd), 0.), 75.);
}
vec3 postProcess(in vec3 col, in vec2 q)
{
col=pow(clamp(col,0.0,1.0),vec3(0.45));
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 = 2.0*vec3(1.5, 3.0, 1.0);
// background color
vec3 skyCol = mix(vec3(0.8, 0.8, 1.0)*0.3, vec3(0.8, 0.8, 1.0)*0.6, 0.25 + 0.75*rd.y);
vec3 color = vec3(0.5, 0.8, 1.0);
float t = rayMarch(ro,rd);
vec3 pos = ro + t*rd;
vec3 nor = vec3(0.0, 1.0, 0.0);
if (t < MAX_RAY_LENGTH && pos.y > 0.0)
{
// Ray intersected object
nor = normal(pos);
vec3 anor = abs(nor);
color = 0.9*color*dot(anor, vec3(1.0, 0.0, 0.0)) + 0.8*color*dot(anor, vec3(0.0, 1.0, 0.0)) + 0.7*color*dot(anor, vec3(0.0, 0.0, 1.0));
}
else if (pos.y > 0.0)
{
// Ray intersected sky
return skyCol;
}
else
{
// Ray intersected plane
t = -ro.y/rd.y;
pos = ro + t*rd;
nor = vec3(0.0, 1.0, 0.0);
vec2 pp = mod(pos.xz, vec2(2.0)) - vec2(1.0);
color = pp.x*pp.y > 0.0 ? vec3(0.3, 0.3, 0.4) : vec3(0.1, 0.1, 0.2);
nor = vec3(0.0, 0.0, 1.0);
float d = distanceEstimator(pos);
float d2 = pow(d, 1.2);
float dd = floor(d2/0.5);
float mm = d2 - 0.5*dd;
if (dd > 4.0)
{
}
else
{
float ss = pow(0.9, dd);
float b = step(0.4, mm);
if (b > 0.0)
{
color = vec3(0.8);
}
else
{
}
}
}
vec3 lv = lightPos - pos;
float ll2 = dot(lv, lv);
float ll = sqrt(ll2);
vec3 ld = lv / ll;
float sha = softShadow(pos, ld, ll, 0.01, 64.0);
float dm = min(1.0, 40.0/ll2);
float dif = max(dot(nor,ld),0.0)*dm;
float occ = 1.0 - ambientOcclusion(pos, nor);
float spe = specular(nor, ld, rd);
float l = dif*occ*sha;
float lin = mix(0.2, 1.0, l);
vec3 col = lin*color + spe*sha;
float f = (clamp(t, FADE_RAY_LENGTH, MAX_RAY_LENGTH) - FADE_RAY_LENGTH) / (MAX_RAY_LENGTH - FADE_RAY_LENGTH);
return mix(col, skyCol, pow(f, 0.75));
}
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
vec2 q=fragCoord.xy/iResolution.xy;
vec2 p = -1.0 + 2.0*q;
p.x *= iResolution.x/iResolution.y;
float ctime = iTime/2.0;
// camera
vec3 ro = 2.0*vec3(2.0, 1.5, 0.2);
//vec3 ro = 2.0*vec3(2.0*cos(ctime), 1.0, 2.0*sin(ctime));
vec3 ww = normalize(vec3(0.0, 1.0, 0.0) - 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.5*ww );
vec3 col = render(ro, rd);
fragColor = vec4(postProcess(col, q),1.0);
}
// A humble beginning
#define TOLERANCE 0.001
#define MAX_RAY_LENGTH 32.0
#define MAX_RAY_MARCHES 128
float sdSphere(in vec3 p, in float r)
{
return length(p) - r;
}
float distanceEstimator(in vec3 p)
{
return sdSphere(p, 1.0);
}
float rayMarch(in vec3 ro, in vec3 rd)
{
float t = 0.0;
for (int i = 0; i < MAX_RAY_MARCHES; i++)
{
float distance = distanceEstimator(ro + rd*t);
if (distance < TOLERANCE || t > MAX_RAY_LENGTH) break;
t += distance;
}
return t;
}
vec3 render(in vec3 ro, in vec3 rd)
{
// background color
vec3 skyCol = mix(vec3(0.8, 0.8, 1.0)*0.3, vec3(0.8, 0.8, 1.0)*0.6, 0.25 + 0.75*rd.y);
vec3 color = vec3(0.5, 0.8, 1.0);
float t = rayMarch(ro,rd);
if (t < MAX_RAY_LENGTH)
{
// Ray intersected object
return color;
}
else
{
// Ray intersected sky
return skyCol;
}
}
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
vec2 q=fragCoord.xy/iResolution.xy;
vec2 p = -1.0 + 2.0*q;
p.x *= iResolution.x/iResolution.y;
float ctime = iTime/2.0;
// camera
vec3 ro = 3.0*vec3(2.0, 1.0, 0.2);
vec3 ww = normalize(vec3(0.0, 0.0, 0.0) - ro);
vec3 uu = normalize(cross( vec3(0.0,1.0,0.0), ww ));
vec3 vv = normalize(cross(ww,uu));
// ray direction
vec3 rd = normalize( p.x*uu + p.y*vv + 2.5*ww );
vec3 col = render(ro, rd);
fragColor = vec4(col, 1.0);
}
// Some lightning
#define TOLERANCE 0.001
#define MAX_RAY_LENGTH 32.0
#define MAX_RAY_MARCHES 128
float maxComp(in vec3 p)
{
return max(p.x,max(p.y,p.z));
}
float sdSphere(in vec3 p, in float r)
{
return length(p) - r;
}
float sdBox(vec3 p, vec3 b)
{
vec3 di = abs(p) - b;
float mc = maxComp(di);
return min(mc,length(max(di,0.0)));
}
float distanceEstimator(in vec3 p)
{
return sdSphere(p - vec3(0.0, 1.0, 0.0), 1.0);
}
float rayMarch(in vec3 ro, in vec3 rd)
{
float t = 0.0;
for (int i = 0; i < MAX_RAY_MARCHES; i++)
{
float distance = distanceEstimator(ro + rd*t);
if (distance < TOLERANCE || t > MAX_RAY_LENGTH) break;
t += distance;
}
return t;
}
vec3 normal(in vec3 pos)
{
vec3 eps = vec3(.001,0.0,0.0);
vec3 nor;
nor.x = distanceEstimator(pos+eps.xyy) - distanceEstimator(pos-eps.xyy);
nor.y = distanceEstimator(pos+eps.yxy) - distanceEstimator(pos-eps.yxy);
nor.z = distanceEstimator(pos+eps.yyx) - distanceEstimator(pos-eps.yyx);
return normalize(nor);
}
float diffuse(in vec3 nor, in vec3 ld)
{
return max(dot(nor, ld),0.0);
}
float specular(in vec3 nor, in vec3 ld, in vec3 rd)
{
return pow(max(dot(reflect(-ld, nor), -rd), 0.), 75.);
}
vec3 render(in vec3 ro, in vec3 rd)
{
vec3 lightPos = 2.0*vec3(1.5, 3.0, -1.0);
// background color
vec3 skyCol = mix(vec3(0.8, 0.8, 1.0)*0.3, vec3(0.8, 0.8, 1.0)*0.6, 0.25 + 0.75*rd.y);
float t = rayMarch(ro,rd);
if (t < MAX_RAY_LENGTH)
{
// Ray intersected object
vec3 pos = ro + t*rd;
vec3 nor = normal(pos);
vec3 color= vec3(0.5, 0.8, 1.0);
vec3 ld = normalize(lightPos - pos);
//float dif = diffuse(nor, ld);
//float spe = specular(nor, ld, rd);
float dif = 1.0;
float spe = 0.0;
float lin = mix(0.2, 1.0, dif);
vec3 col = lin*color + spe;
return col;
}
else
{
// Ray intersected sky
return skyCol;
}
}
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
vec2 q=fragCoord.xy/iResolution.xy;
vec2 p = -1.0 + 2.0*q;
p.x *= iResolution.x/iResolution.y;
float ctime = iTime/2.0;
// camera
vec3 ro = 2.0*vec3(2.0, 1.0, 0.2);
//vec3 ro = 2.0*vec3(2.0*cos(ctime), 1.0, 2.0*sin(ctime));
vec3 ww = normalize(vec3(0.0, 1.0, 0.0) - 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.5*ww );
vec3 col = render(ro, rd);
fragColor = vec4(col,1.0);
}
// Shadows adds immersion
#define TOLERANCE 0.001
#define MAX_RAY_LENGTH 32.0
#define FADE_RAY_LENGTH 16.0
#define MAX_RAY_MARCHES 128
#define PI 3.141592654
#define TAU (2.0*PI)
float maxComp(in vec3 p)
{
return max(p.x,max(p.y,p.z));
}
float sdSphere(in vec3 p, in float r)
{
return length(p) - r;
}
float sdBox(vec3 p, vec3 b)
{
vec3 di = abs(p) - b;
float mc = maxComp(di);
return min(mc,length(max(di,0.0)));
}
float complexBall(in vec3 p)
{
p -=vec3(0.0, 1.0, 0.0);
vec3 r = vec3(0.2);
vec3 rp = mod(p, r) - 0.5*r;
float d1 = sdSphere(p, 1.0);
float d2 = sdBox(rp, vec3(0.08));
return max(d1, -d2);
}
float distanceEstimator(in vec3 p)
{
// vec2 r = vec2(3.0);
// p.xz = mod(p.xz, r) - 0.5*r;
return complexBall(p);
}
float rayMarch(in vec3 ro, in vec3 rd)
{
float t = 0.0;
for (int i = 0; i < MAX_RAY_MARCHES; i++)
{
float distance = distanceEstimator(ro + rd*t);
if (distance < TOLERANCE || t > MAX_RAY_LENGTH) break;
t += distance;
}
return t;
}
vec3 normal(in vec3 pos)
{
vec3 eps = vec3(.001,0.0,0.0);
vec3 nor;
nor.x = distanceEstimator(pos+eps.xyy) - distanceEstimator(pos-eps.xyy);
nor.y = distanceEstimator(pos+eps.yxy) - distanceEstimator(pos-eps.yxy);
nor.z = distanceEstimator(pos+eps.yyx) - distanceEstimator(pos-eps.yyx);
return normalize(nor);
}
float ambientOcclusion(vec3 p, vec3 n)
{
float stepSize = 0.01;
float t = stepSize;
float oc = 0.0;
for(int i = 0; i < 10; i++)
{
float d = distanceEstimator(p + n * t);
oc += t - d; // Actual distance to surface - distance field value
t += stepSize;
}
return clamp(oc, 0.0, 1.0);
}
float softShadow(in vec3 ro, in vec3 rd, float mint, float k)
{
float res = 1.0;
float t = mint;
for (int i=0; i<32; i++)
{
float distance = distanceEstimator(ro + rd*t);
res = min(res, k*distance/t);
t += max(distance, mint*0.2);
}
return clamp(res,0.25,1.0);
}
float diffuse(in vec3 nor, in vec3 ld)
{
return max(dot(nor, ld),0.0);
}
float specular(in vec3 nor, in vec3 ld, in vec3 rd)
{
return pow(max(dot(reflect(-ld, nor), -rd), 0.), 75.);
}
vec3 render(in vec3 ro, in vec3 rd)
{
vec3 lightPos = 2.0*vec3(1.5, 3.0, 1.0);
// background color
vec3 skyCol = mix(vec3(0.8, 0.8, 1.0)*0.3, vec3(0.8, 0.8, 1.0)*0.6, 0.25 + 0.75*rd.y);
vec3 color = vec3(0.5, 0.8, 1.0);
float t = rayMarch(ro,rd);
vec3 pos = ro + t*rd;
vec3 nor = vec3(0.0, 1.0, 0.0);
if (t < MAX_RAY_LENGTH && pos.y > 0.0)
{
// Ray intersected object
nor = normal(pos);
}
else if (pos.y > 0.0)
{
// Ray intersected sky
return skyCol;
}
else
{
// Ray intersected plane
t = -ro.y/rd.y;
pos = ro + t*rd;
nor = vec3(0.0, 1.0, 0.0);
vec2 pp = mod(pos.xz, vec2(2.0)) - vec2(1.0);
color = pp.x*pp.y > 0.0 ? vec3(0.3, 0.3, 0.4) : vec3(0.1, 0.1, 0.2);
}
vec3 ld = normalize(lightPos - pos);
float d2 = dot(lightPos - pos, lightPos - pos);
float dm = min(1.0, 40.0/d2);
float dif = max(dot(nor,ld),0.0)*dm;
float spe = specular(nor, ld, rd);
//float sha = softShadow(pos, ld, 0.01, 16.0);
//float occ = 1.0 - ambientOcclusion(pos, nor);
float sha = 1.0;
float occ = 1.0;
float lin = mix(0.2, 1.0, dif*occ*sha);
vec3 col = lin*color + spe*sha;
float f = (clamp(t, FADE_RAY_LENGTH, MAX_RAY_LENGTH) - FADE_RAY_LENGTH) / (MAX_RAY_LENGTH - FADE_RAY_LENGTH);
return mix(col, skyCol, pow(f, 0.75));
}
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
vec2 q=fragCoord.xy/iResolution.xy;
vec2 p = -1.0 + 2.0*q;
p.x *= iResolution.x/iResolution.y;
float ctime = iTime/2.0;
// camera
vec3 ro = 2.0*vec3(2.0, 1.0, 0.2);
//vec3 ro = 2.5*vec3(2.0*cos(ctime), 1.0, 2.0*sin(ctime));
vec3 ww = normalize(vec3(0.0, 1.0, 0.0) - 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.5*ww );
vec3 col = render(ro, rd);
fragColor = vec4(col,1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment