Created
July 15, 2019 08:45
-
-
Save mrange/f3031701ab3ad163feb06a1d20f3bc57 to your computer and use it in GitHub Desktop.
dodec
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; | |
//////////////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
precision highp float; | |
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.00001 | |
#define NORM_OFF 0.0001 | |
#define MAX_RAY_LENGTH 16.0 | |
#define MAX_RAY_MARCHES 70 | |
#define PI 3.141592654 | |
#define TAU (2.0*PI) | |
#define BOXSIZE 0.2 | |
#define PERIOD 15.0 | |
#define CURRENT_PERIOD int(iTime/PERIOD) | |
#define TIME_IN_PERIOD mod(iTime,PERIOD) | |
#define FADE_BOX_ROTATE_BEGIN 10.0 | |
#define FADE_BOX_ROTATE_END 20.0 | |
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); } | |
float rand(vec3 r) | |
{ | |
return fract(sin(dot(r.xy,vec2(1.38984*sin(r.z),1.13233*cos(r.z))))*653758.5453); | |
} | |
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; | |
} | |
vec4 mod4(inout vec4 p, vec4 size) | |
{ | |
vec4 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 softMin2(in float a, in float b, in float k) | |
{ | |
if (a*a + b*b > 4.0) | |
{ | |
return min(a, b); | |
} | |
else | |
{ | |
return softMin(a, b, 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; | |
} | |
float sdHoleyBox(in vec3 p) | |
{ | |
vec3 bp = p; | |
float bd = sdSoftBox(bp, BOXSIZE); | |
mod3(bp, vec3(0.62*BOXSIZE)); | |
float msd = sdSphere(bp, 0.38*BOXSIZE); | |
float hbd = max(bd, -msd); | |
return hbd; | |
} | |
mat4 mscale(vec3 s) | |
{ | |
return mat4( | |
s.x, 0.0, 0.0, 0.0, | |
0.0, s.y, 0.0, 0.0, | |
0.0, 0.0, s.z, 0.0, | |
0.0, 0.0, 0.0, 1.0); | |
} | |
mat4 mrotX(in float a) | |
{ | |
float c = cos(a); | |
float s = sin(a); | |
return mat4( | |
c,-s, 0, 0, | |
s, c, 0, 0, | |
0, 0, 1, 0, | |
0, 0, 0, 0); | |
} | |
mat4 mrotY(in float a) | |
{ | |
float c = cos(a); | |
float s = sin(a); | |
return mat4( | |
c, 0,-s, 0, | |
0, 1, 0, 0, | |
s, 0, c, 0, | |
0, 0, 0, 1); | |
} | |
mat4 mrotZ(in float a) | |
{ | |
float c = cos(a); | |
float s = sin(a); | |
return mat4( | |
1, 0, 0, 0, | |
0, c,-s, 0, | |
0, s, c, 0, | |
0, 0, 0, 1); | |
} | |
mat4 mtrans(in vec3 t) | |
{ | |
return mat4( | |
1, 0, 0, t.x, | |
0, 1, 0, t.y, | |
0, 0, 1, t.z, | |
0, 0, 0, 1); | |
} | |
float sdCapsule(vec3 p, float r, float c) | |
{ | |
return mix(length(p.xz) - r, length(vec3(p.x, abs(p.y) - c, p.z)) - r, step(c, abs(p.y))); | |
} | |
const float Size = 1; | |
const vec3 plnormal = normalize(vec3(1, 1, -1)); | |
#define Phi (.5*(1.+sqrt(5.))) | |
const int Iterations = 1; | |
const vec3 n1 = normalize(vec3(-Phi,Phi-1.0,1.0)); | |
const vec3 n2 = normalize(vec3(1.0,-Phi,Phi+1.0)); | |
const vec3 n3 = normalize(vec3(0.0,0.0,-1.0)); | |
float dodec(in vec3 z) | |
{ | |
float t; | |
// Folds. | |
//Dodecahedral.. you can use other sets of foldings! | |
z = abs(z); | |
t=dot(z,n1); if (t>0.0) { z-=2.0*t*n1; } | |
t=dot(z,n2); if (t>0.0) { z-=2.0*t*n2; } | |
z = abs(z); | |
t=dot(z,n1); if (t>0.0) { z-=2.0*t*n1; } | |
t=dot(z,n2); if (t>0.0) { z-=2.0*t*n2; } | |
z = abs(z); | |
//combine DEs... explore different combinations ;) | |
//the base DE is the distance to the plane going through vec3(Size,0.,0.) and which normal is plnormal | |
float dmin=dot(z-vec3(Size,0.,0.),normalize(plnormal)); | |
return (dmin); | |
} | |
void pR45(inout vec2 p) { | |
p = (p + vec2(p.y, -p.x))*sqrt(0.5); | |
} | |
float pMod1(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 fOpUnionColumns(float a, float b, float r, float n) { | |
if ((a < r) && (b < r)) { | |
vec2 p = vec2(a, b); | |
float columnradius = r*sqrt(2)/((n-1)*2+sqrt(2)); | |
pR45(p); | |
p.x -= sqrt(2)/2*r; | |
p.x += columnradius*sqrt(2); | |
if (mod(n,2) == 1) { | |
p.y += columnradius; | |
} | |
// At this point, we have turned 45 degrees and moved at a point on the | |
// diagonal that we want to place the columns on. | |
// Now, repeat the domain along this direction and place a circle. | |
pMod1(p.y, columnradius*2); | |
float result = length(p) - columnradius; | |
result = min(result, p.x); | |
result = min(result, a); | |
return min(result, b); | |
} else { | |
return min(a, b); | |
} | |
} | |
float de(in vec3 p) | |
{ | |
vec3 z = p; | |
float t; | |
z = abs(z); | |
t=dot(z,n1); if (t>0.0) { z-=2.0*t*n1; } | |
t=dot(z,n2); if (t>0.0) { z-=2.0*t*n2; } | |
z = abs(z); | |
t=dot(z,n1); if (t>0.0) { z-=2.0*t*n1; } | |
t=dot(z,n2); if (t>0.0) { z-=2.0*t*n2; } | |
z = abs(z); | |
//combine DEs... explore different combinations ;) | |
//the base DE is the distance to the plane going through vec3(Size,0.,0.) and which normal is plnormal | |
float lz = length(p); | |
vec3 pn1 = plnormal; | |
vec3 pn2 = vec3(1,0,0); | |
vec3 pn3 = normalize(vec3(1,1,1)); | |
rot(pn1.yz, 0.45); | |
rot(pn2.xz, -1.7); | |
rot(pn3.xy, 0.5); | |
float dmin1=dot(z-vec3(Size,0,0),pn1); | |
float dmin2=dot(z-vec3(Size*0.4,1,0),pn2); | |
float dmin3=dot(z-vec3(Size*1.2,0,0),pn3); | |
float dmin = max(max(-dmin1, -dmin2), dmin3); | |
// dmin = dmin3; | |
return dmin; | |
} | |
float map(in vec3 p, out int m) | |
{ | |
float d1 = de(p); | |
m = 1; | |
return d1; | |
} | |
float rayMarch(in vec3 ro, in vec3 rd, out int mat, out int iter) | |
{ | |
float t = 0.0; | |
float distance; | |
int i; | |
for (i = 0; i < MAX_RAY_MARCHES; i++) | |
{ | |
distance = map(ro + rd*t, mat); | |
if (distance < TOLERANCE || t > MAX_RAY_LENGTH) break; | |
t += distance; | |
} | |
iter = i; | |
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) | |
{ | |
// background color | |
vec3 color = vec3(0.5, 0.8, 1.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; | |
if (t < MAX_RAY_LENGTH) | |
{ | |
// Ray intersected object | |
nor = normal(pos); | |
float d2 = abs(dot(-rd, nor)); | |
switch(mat) | |
{ | |
case 0: | |
color = mix(vec3(1.0), nor*nor, 0.5); | |
ndif = 0.75; | |
nref = 0.7; | |
break; | |
case 1: | |
color = vec3(0.9) + abs(nor.zxy)*0.1; | |
ndif = 0.75; | |
nref = 0.7; | |
break; | |
case 2: | |
color = vec3(0.25) + abs(nor.zxy)*0.05; | |
ndif = 0.5; | |
nref = 0.9; | |
break; | |
default: | |
color = nor*nor; | |
break; | |
} | |
} | |
else | |
{ | |
// Ray intersected sky | |
return skyColor(rd); | |
} | |
vec3 ref = reflect(rd, nor); | |
vec3 rcol = skyColor(ref); | |
vec3 ld0 = vec3(0.0, 1.0, 0.0); | |
vec3 lv1 = lightPos1 - pos; | |
float ll1 = length(lv1); | |
vec3 ld1 = lv1 / ll1; | |
vec3 lv2 = lightPos2 - pos; | |
float ll2 = length(lv2); | |
vec3 ld2 = lv2 / ll2; | |
int rmat = 0; | |
int riter = 0; | |
float st = rayMarch(pos + ref*10.0*TOLERANCE, ref, rmat, riter); | |
float sha1 = pow(st/MAX_RAY_LENGTH, 0.2); | |
float sha2 = 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 = (MAX_RAY_MARCHES + MAX_RAY_MARCHES - iter) / float(2.0*MAX_RAY_MARCHES); | |
// float spe = pow(max(dot(reflect(-ld, nor), -rd), 0.), nspe); | |
// float bac = max(0.4 + 0.6*dot(nor,vec3(-ld.x,ld.y,-ld.z)),0.0); | |
// float lin = mix(0.2, 1.0, pow(dif,ndif)*occ + 0.3*bac*(0.5+0.5*occ)); | |
float bac = 0.2; | |
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); | |
// nref = 1.0; | |
vec3 col = mix(rcol*sha2, color*(col0 + col1 + col2)/2.0, nref); | |
return col; | |
} | |
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; | |
} | |
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; | |
vec3 ro = mix(2.5, 1.0, 0.)*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), 0.0); | |
vec3 up = vec3(0.0, 1.0, 0.0); | |
rot(ro.xz, TAU*iTime/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); | |
float yy = -1 + 2.0*60*iTimeDelta; | |
if (yy > p.y) | |
{ | |
// col += vec3(0.9); | |
} | |
fragColor = vec4(mix(col, vec3(1.0), 0.0),1.0); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment