Skip to content

Instantly share code, notes, and snippets.

@mrange
Created March 7, 2021 11:50
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/eb7799fe5250e6dcffda63f58b563506 to your computer and use it in GitHub Desktop.
Save mrange/eb7799fe5250e6dcffda63f58b563506 to your computer and use it in GitHub Desktop.
amiga
#define TOLERANCE 0.0001
#define NORM_OFF 0.001
#define MAX_RAY_LENGTH 12.0
#define MAX_RAY_MARCHES 65
#define MAX_SHADOW_MARCHES 15
#define MAX_REFLECTIONS 5
#define PI 3.141592654
#define TAU (2.0*PI)
#define ROT(a) mat2(cos(a), sin(a), -sin(a), cos(a))
#define TIME iTime
#define TTIME (TAU*TIME)
#define L2(x) dot(x,x)
vec3 gbaseColor = vec3(0.0);
float grefFactor = 1.0;
mat2 grot = ROT(0.0);
float tanh_approx(float x) {
// return tanh(x);
float x2 = x*x;
return clamp(x*(27.0 + x2)/(27.0+9.0*x2), -1.0, 1.0);
}
float pmin(float a, float b, float k) {
float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
return mix( b, a, h ) - k*h*(1.0-h);
}
float pmax(float a, float b, float k) {
return -pmin(-a, -b, k);
}
float smin(float a, float b, float r, float n) {
float s = r/n;
float u = b-r;
return min(min(a,b), 0.5 * (u + a + abs ((mod (u - a + s, 2 * s)) - s)));
}
float smax(float a, float b, float r, float n) {
return -smin(-a, -b, r, n);
}
vec3 postProcess(vec3 col, vec2 q) {
col = clamp(col, 0.0, 1.0);
col = pow(col, 1.0/vec3(2.2));
col = col*0.6+0.4*col*col*(3.0-2.0*col);
col = mix(col, vec3(dot(col, vec3(0.33))), -0.4);
col *=0.5+0.5*pow(19.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.7);
return col;
}
const vec3 lightPos = 2.0*vec3(4.0, 3.0, 1.5);
const vec3 backLightPos = lightPos.x*vec3(-1.0, 1.0, -1.0);
const vec3 skyCol1 = vec3(0.2, 0.4, 0.6);
const vec3 skyCol2 = vec3(0.4, 0.7, 1.0);
const vec3 sunCol = vec3(8.0,7.0,6.0)/8.0;
float planeIntersect(vec3 ro, vec3 rd, float mint) {
vec3 p = ro + rd*mint;
return (-.85-p.y)/rd.y;
}
float hash(float co) {
co += 100.0;
return fract(sin(co*12.9898) * 13758.5453);
}
float hash(vec3 co) {
co += 100.0;
return fract(sin(dot(co, vec3(12.9898,58.233, 12.9898+58.233))) * 13758.5453);
}
float torus(vec3 p, vec2 t) {
vec2 q = vec2(length(p.xz)-t.x,p.y);
return length(q)-t.y;
}
float sphere(vec3 p, float r) {
return length(p) - r;
}
float mod1(inout float p, float size) {
float halfsize = size*0.5;
float c = floor((p + halfsize)/size);
p = mod(p + halfsize, size) - halfsize;
return c;
}
float saturate(float a) { return clamp(a, 0.0, 1.0); }
vec4 sphereColor(vec3 p) {
float lxz = length(p.xz);
const float d0 = 4.0;
const float d1 = 4.0;
const float m0 = PI/2.0/d0;
const float m1 = PI/2.0/d1;
float a0 = atan(p.y, lxz)+PI/4.0/d0;
float n0 = mod1(a0, m0);
float x0 = fract(n0*0.5)*2.0;
float a1 = atan(p.x, p.z)+PI/4.0/d1;
float n1 = mod1(a1, m1);
float x1 = fract(n1*0.5)*2.0;
vec2 aa = abs(vec2(a0/m0, a1/m1));
float t = max(aa.x, aa.y);
int m = int(round(x0))^int(round(x1));
return m > 0 ? vec4(1.0, 1.0, 1.0, t) : vec4(1.0, 0.0, 0.0, t);
}
vec3 skyColor(vec3 rd) {
const vec3 sunDir = normalize(lightPos);
float sunDot = max(dot(rd, sunDir), 0.0);
vec3 final = vec3(0.);
float roundBox = length(max(abs(rd.xz/max(0.0,rd.y))-vec2(0.5, 0.5),0.0))-0.1;
final += vec3(0.75)* pow(saturate(1.0 - roundBox*0.5), 9.0);
final += mix(skyCol1, skyCol2, rd.y);
final += 0.5*sunCol*pow(sunDot, 20.0);
final += 4.0*sunCol*pow(sunDot, 400.0);
return final;
}
float df(vec3 p) {
vec3 p0 = p;
p0 -= vec3(.0, 0.0, 0.0);
p0.xy *= ROT(PI/12.0);
p0.xz *= grot;
vec3 p1 = p;
p1 -= vec3(1.0+0.75*sin(TIME), 0.0, 0.0);
p1.xy *= ROT(PI/12.0);
// p1.xz *= grot;
p1.xy *= grot;
float d0 = sphere(p0, 0.75);
// float d1 = sphere(p1, 0.35);
float d1 = torus(p1, 0.45*vec2(1.0, 0.1));
vec4 c0 = sphereColor(p0);
vec4 c1 = sphereColor(p1);
float d = 1E6;
d0 = pmax(d0, -d1, 0.5);
if (d0 < d) {
grefFactor = 0.75;
gbaseColor = c0.xyz;
// d = d0-0.01*(1.0-tanh_approx(10*c0.w-5.1));
d = d0;
}
if (d1 < d) {
grefFactor = 0.75;
gbaseColor = c1.xyz;
// d = d1-0.01*(1.0-tanh_approx(10*c1.w-5.1));
d = d1;
}
return d;
}
vec3 normal(vec3 pos) {
vec3 eps = vec3(NORM_OFF, 0.0, 0.0);
vec3 nor;
nor.x = df(pos+eps.xyy) - df(pos-eps.xyy);
nor.y = df(pos+eps.yxy) - df(pos-eps.yxy);
nor.z = df(pos+eps.yyx) - df(pos-eps.yyx);
return normalize(nor);
}
float rayMarch(vec3 ro, vec3 rd, float initial, out float nearest, out int iter) {
float t = initial;
float n = 1E6;
int ii = 0;
for (int i = 0; i < MAX_RAY_MARCHES; ++i) {
ii = i;
vec3 p = ro + rd*t;
float d = df(p);
n = min(n, d);
if (d < TOLERANCE || t > MAX_RAY_LENGTH) break;
t += d;
}
iter = ii;
nearest = n;
return t;
}
float softShadow(vec3 ps, vec3 ld, float mint, float k) {
float res = 1.0;
float t = mint*6.0;
int mat;
for (int i=0; i<MAX_SHADOW_MARCHES; ++i) {
vec3 p = ps + ld*t;
float d = df(p);
res = min(res, k*d/t);
if (res < TOLERANCE) break;
t += max(d, mint);
}
return clamp(res, 0.0, 1.0);
}
vec3 render(vec3 ro, vec3 rd) {
vec3 finalCol = vec3(0.0);
float aggRefFactor = 1.0;
vec3 bg = skyColor(rd);
for (int rc = 0; rc < MAX_REFLECTIONS; ++rc) {
if (aggRefFactor < 0.05) break;
vec3 sky = skyColor(rd);
const float mint = 0.05;
float tp = planeIntersect(ro, rd, mint);
int iter;
float nearest;
float tm = rayMarch(ro, rd, mint, nearest, iter);
vec3 baseColor = gbaseColor;
float refFactor = grefFactor;
// float shine = 0.25*tanh_approx(0.25/(nearest));
float shine = exp(-5*nearest);
// shine = rc < 2 ? shine : 0.0;
const float shinef = 0.125;
const vec3 shineCol = vec3(1.25).zyx;
shine *= shinef;
if(tm >= MAX_RAY_LENGTH && tp <= 0.0) {
// We hit the sky
finalCol += aggRefFactor*mix(sky, shineCol, shine);
break;
}
vec3 p;
vec3 nor;
float fakeAo;
if (tm < MAX_RAY_LENGTH) {
p = ro + tm*rd;
nor = normal(p);
fakeAo = 1.0 - smoothstep(0.5, 1.2, float(iter)/float(MAX_RAY_MARCHES));
} else {
p = ro + tp*rd;
baseColor = vec3(0.75);
refFactor = 0.75;
// nor = normalize(vec3(0.0, 1.0, 0.0) + 0.25/(0.2+0.2*L2(p.xz))*vec3(sin(-TIME+3*length(p.xz)), 0.0, 0.0).xzy);
nor = vec3(0.0, 1.0, 0.0);
fakeAo = 1.0;
}
refFactor *= pow(abs(dot(nor, rd)), 0.25);
vec3 ld = normalize(lightPos - p);
vec3 bld = normalize(backLightPos - p);
float dif = max(dot(nor, ld), 0.0);
float bdif = max(dot(nor, bld), 0.0);
float spe = pow(max(dot(reflect(ld, nor), rd), 0.0), 40.0);
float sha = softShadow(p, ld, 0.1, 4.0);
vec3 col = 0.8*baseColor*mix(0.2, 1.0, dif*sha*fakeAo) + 0.25*spe;
col += baseColor*mix(0.0, 0.2, bdif);
col *= refFactor;
float yy = 1.0-exp(-4*float(iter)/float(MAX_RAY_MARCHES));
col = mix(col, shineCol, max(shine, yy*shinef));
finalCol += aggRefFactor*(col);
aggRefFactor *= (1.0 - refFactor);
ro = p;
rd = reflect(rd, nor);
}
/*
finalCol = clamp(finalCol, 0.0, 1.0);
vec3 dfinalColdx = dFdx(finalCol);
vec3 dfinalColdy = dFdy(finalCol);
float r = hash(rd);
if (length(dfinalColdy) + length(dfinalColdx) > 0.25) {
finalCol = mix(finalCol, bg, length(dfinalColdy)*0.5) ;
// finalCol = vec3(1.0, 0.0, 0.0);
}
*/
return finalCol;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
grot = ROT(TTIME/10.0);
vec2 q=fragCoord.xy/iResolution.xy;
vec2 p = -1.0 + 2.0*q;
p.x *= iResolution.x/iResolution.y;
vec3 ro = 0.75*vec3(6.0, 0.0, 0.0);
vec3 la = vec3(0.0, .0, 0.0);
vec3 up = vec3(0.0, 1.0, 0.0);
ro.xz *= ROT(PI/6.0+sin(TIME*sqrt(0.5)));
vec3 ww = normalize(la - ro);
vec3 uu = normalize(cross(up, ww));
vec3 vv = normalize(cross(ww,uu));
vec3 rd = normalize(p.x*uu + p.y*vv + 2.5*ww);
vec3 col = render(ro, rd);
col = postProcess(col, q);
fragColor = vec4(col, 1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment