Created
March 7, 2021 11:50
-
-
Save mrange/eb7799fe5250e6dcffda63f58b563506 to your computer and use it in GitHub Desktop.
amiga
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
#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