Last active
October 9, 2019 04:13
-
-
Save mrange/00ffeac975a195295797f742242592c7 to your computer and use it in GitHub Desktop.
impulse box
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
#version 150 | |
in VertexData | |
{ | |
vec4 v_position; | |
vec3 v_normal; | |
vec2 v_texcoord; | |
} inData; | |
out vec4 fragColor; | |
//////////////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
uniform vec2 iResolution; | |
uniform float iTime; | |
uniform float iTimeDelta; | |
uniform int iFrame; | |
uniform vec4 iMouse; | |
uniform sampler2D iChannel0; | |
uniform sampler2D iChannel1; | |
uniform sampler2D iChannel2; | |
uniform sampler2D iChannel3; | |
uniform vec4 iDate; | |
uniform float iSampleRate; | |
void mainImage(out vec4, in vec2); | |
void main(void) { mainImage(fragColor,inData.v_texcoord * iResolution.xy); } | |
//////////////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
// 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 NORM_OFF 0.001 | |
#define MAX_RAY_LENGTH 6.0 | |
#define MAX_RAY_MARCHES 70 | |
#define PI 3.141592654 | |
#define TAU (2.0*PI) | |
#define BOXSIZE 0.2 | |
#define FADE_BOX_ROTATE_BEGIN 10.0 | |
#define FADE_BOX_ROTATE_END 20.0 | |
#define TIME (iTime*0.2) | |
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); } | |
vec3 toSpherical(vec3 p) | |
{ | |
float l = length(p); | |
return vec3(length(p), acos(p.z/l), atan(p.y, p.x)); | |
} | |
vec3 toRectangular(vec3 p) | |
{ | |
float l = length(p); | |
return vec3(p.x*sin(p.y)*cos(p.z), p.x*sin(p.y)*sin(p.z), p.x*cos(p.y)); | |
} | |
vec3 mod3(inout vec3 p, vec3 size) | |
{ | |
vec3 c = floor((p + size*0.5)/size); | |
p = mod(p + size*0.5, size) - size*0.5; | |
return c; | |
} | |
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, in 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 unionRound(float a, float b, float r) | |
{ | |
vec2 u = max(vec2(r - a,r - b), vec2(0)); | |
return max(r, min (a, b)) - length(u); | |
} | |
float softMin(in float a, in float b, in 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(in vec3 p, in vec3 b) | |
{ | |
vec3 di = abs(p) - b; | |
float mc = maxComp(di); | |
return min(mc,length(max(di,0.0))); | |
} | |
float sdSoftBox(in vec3 p, in float r) | |
{ | |
p *= p; | |
p *= p; | |
p *= p; | |
return pow(p.x + p.y + p.z, 1.0/8.0) - r; | |
} | |
float sdCross(in vec3 p) | |
{ | |
float da = maxComp(abs(p.xy)); | |
float db = maxComp(abs(p.yz)); | |
float dc = maxComp(abs(p.zx)); | |
return min(da,min(db,dc))-1.0; | |
} | |
float sdPlane(in vec3 p, in vec3 n, in float m) | |
{ | |
return dot(p, n) + m; | |
} | |
void nerdRotate(inout vec3 p) | |
{ | |
float a2 = 2.0*TIME/sqrt(2.0); | |
float a3 = 1.0*TIME/sqrt(3.0); | |
float a5 = 0.5*TIME/sqrt(5.0); | |
rot(p.yz, a5); | |
rot(p.xy, -a3); | |
rot(p.xz, -a2); | |
} | |
float impulseCube(in vec3 p, in float celld, in float celll, out int m) | |
{ | |
vec3 bp = p; | |
float cs = BOXSIZE*0.8; | |
float cd = max(length(p.xy) - cs*0.3, sdSphere(bp, 1.2*BOXSIZE)); | |
float hbd = min(max(sdSoftBox(bp, BOXSIZE), -sdCross(bp/cs)*cs), cd); | |
float bbd = sdBox(bp, vec3(cs)); | |
vec3 rbp = toSpherical(bp); | |
rbp.y += TIME*0.5; | |
bp = toRectangular(rbp); | |
vec3 cell = mod3(bp, vec3(cs*celld)); | |
float id = sdSoftBox(bp, cs*celll); | |
float mbd = max(bbd, id); | |
float d = unionRound(hbd, mbd, BOXSIZE*0.15); | |
if (abs(hbd - d) < 0.01) | |
{ | |
m = 2; | |
} | |
else | |
{ | |
m = 1; | |
} | |
return d; | |
} | |
float map(in vec3 p, out int m) | |
{ | |
const float scale = BOXSIZE; | |
p *= scale; | |
float d = MAX_RAY_LENGTH; | |
nerdRotate(p); | |
d = impulseCube(p, 0.1, 0.03 + 0.02*cos(TIME*0.1), m); | |
return d/scale; | |
} | |
float rayMarch(in vec3 ro, in vec3 rd, out int mat, out int iter) | |
{ | |
float t = 0.0; | |
float distance; | |
for (int i = 0; i < MAX_RAY_MARCHES; i++) | |
{ | |
iter = i; | |
distance = map(ro + rd*t, mat); | |
if (distance < TOLERANCE || t > MAX_RAY_LENGTH) break; | |
t += distance; | |
} | |
if (abs(distance) > 100.0*TOLERANCE) return MAX_RAY_LENGTH; | |
return t; | |
} | |
vec3 normal(in vec3 pos) | |
{ | |
vec3 eps = vec3(NORM_OFF,0.0,0.0); | |
vec3 nor; | |
int mat; | |
nor.x = map(pos+eps.xyy, mat) - map(pos-eps.xyy, mat); | |
nor.y = map(pos+eps.yxy, mat) - map(pos-eps.yxy, mat); | |
nor.z = map(pos+eps.yyx, mat) - map(pos-eps.yyx, mat); | |
return normalize(nor); | |
} | |
const vec3 lightPos1 = 100.0*vec3(-0.3, 0.15, 1.0); | |
const vec3 lightPos2 = 100.0*vec3(-0.33, -0.2, -1.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 skyColor(vec3 rayDir) | |
{ | |
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 += 1.0*pow(lightCol1, vec3(2.0, 1.5, 1.5)) * pow(ld1, 8.0); | |
final += 1.0*lightCol1 * pow(ld1, 200.0); | |
final += 1.0*pow(lightCol2, vec3(2.0, 1.5, 1.5)) * pow(ld2, 8.0); | |
final += 1.0*lightCol2 * pow(ld2, 200.0); | |
return final; | |
} | |
vec3 render(in vec3 ro, in vec3 rd) | |
{ | |
vec3 color = vec3(0.0); | |
int mat = 0; | |
int iter = 0; | |
float t = rayMarch(ro,rd, mat, iter); | |
vec3 pos = ro + t*rd; | |
vec3 nor = vec3(0.0, 1.0, 0.0); | |
float ndif = 1.0; | |
float nref = 0.8; | |
vec3 mref = vec3(1.0); | |
if (t < MAX_RAY_LENGTH) | |
{ | |
nor = normal(pos); | |
float d2 = abs(dot(-rd, nor)); | |
if (mat == 0) | |
{ | |
color = mix(vec3(1.0), nor*nor, 0.5); | |
ndif = 0.75; | |
nref = 0.7; | |
} | |
else if (mat == 1) | |
{ | |
color = vec3(0.9) + abs(nor.zxy)*0.1; | |
ndif = 1.75; | |
nref = 0.7; | |
mref = vec3(1.5, 1.5, 1.75); | |
} | |
else if (mat == 2) | |
{ | |
color = vec3(0.25) + abs(nor.zxy)*0.05; | |
ndif = 0.5; | |
nref = 0.9; | |
} | |
} | |
else | |
{ | |
return skyColor(rd); | |
} | |
vec3 ref = reflect(rd, nor); | |
vec3 rcol = skyColor(ref); | |
vec3 ld0 = vec3(0.0, 1.0, 0.0); | |
vec3 ld1 = normalize(lightPos1 - pos); | |
vec3 ld2 = normalize(lightPos2 - pos); | |
int rmat = 0; | |
int riter = 0; | |
float st = rayMarch(pos + ref*10.0*TOLERANCE, ref, rmat, riter); | |
float sha = st < MAX_RAY_LENGTH ? 0.0 : 1.0; | |
float dif0 = pow(max(dot(nor,ld0),0.0), ndif); | |
float dif1 = pow(max(dot(nor,ld1),0.0), ndif); | |
float dif2 = pow(max(dot(nor,ld2),0.0), ndif); | |
float occ = float(MAX_RAY_MARCHES + MAX_RAY_MARCHES - iter) / 2.0*float(MAX_RAY_MARCHES); | |
vec3 col0 = mix(vec3(1.0), dif0*vec3(1.0), 0.8); | |
vec3 col1 = mix(vec3(1.0), dif1*lightCol1, 0.8); | |
vec3 col2 = mix(vec3(1.0), dif2*lightCol2, 0.8); | |
vec3 col = mix(pow(rcol, vec3(mref))*sha, color*(col0 + col1 + col2)/3.0, nref); | |
return col; | |
} | |
vec3 postProcess(in vec3 col, in vec2 q) | |
{ | |
col*=0.5+0.5*pow(19.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.7); | |
return col; | |
} | |
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 br = smoothstep(FADE_BOX_ROTATE_BEGIN, FADE_BOX_ROTATE_END, TIME); | |
br = 0.0; | |
vec3 ro = mix(1.5, 1.0, br)*vec3(2.0, 1.0, 0.2); | |
vec3 la = mix(vec3(0.0, 0.0, 0.0), vec3(0.0, 1.5/BOXSIZE, 0.0), br); | |
vec3 up = vec3(0.0, 1.0, 0.0); | |
rot(ro.xz, TAU*TIME/30.0); | |
// rot(ro.xz, (iMouse.x + 1.0)/300); | |
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); | |
fragColor = vec4(postProcess(col, q),1.0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment