Created
October 31, 2018 23:22
-
-
Save lunasorcery/7afe42a8c8efb74ac33bb449e6941069 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 410 core | |
uniform float fGlobalTime; // in seconds | |
uniform vec2 v2Resolution; // viewport resolution (in pixels) | |
//#define fGlobalTime 6 | |
layout(location = 0) out vec4 out_color; // out_color must be written in order to see anything | |
#define PI (acos(-1.)) | |
vec2 rotate(vec2 a, float b) | |
{ | |
float c = cos(b); | |
float s = sin(b); | |
return vec2( | |
a.x * c - a.y * s, | |
a.x * s + a.y * c | |
); | |
} | |
// http://mercury.sexy/hg_sdf/ | |
// Repeat around the origin by a fixed angle. | |
// For easier use, num of repetitions is use to specify the angle. | |
float pModPolar(inout vec2 p, float repetitions) { | |
float angle = 2*PI/repetitions; | |
float a = atan(p.y, p.x) + angle/2.; | |
float r = length(p); | |
float c = floor(a/angle); | |
a = mod(a,angle) - angle/2.; | |
p = vec2(cos(a), sin(a))*r; | |
// For an odd number of repetitions, fix cell index of the cell in -x direction | |
// (cell index would be e.g. -5 and 5 in the two halves of the cell): | |
if (abs(c) >= (repetitions/2)) c = abs(c); | |
return c; | |
} | |
float sdSphere(vec3 p, vec3 c, float r) | |
{ | |
return length(p-c)-r; | |
} | |
float sdBox( vec3 p, vec3 b ) | |
{ | |
vec3 d = abs(p) - b; | |
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0)); | |
} | |
float sdTriPrism( vec3 p, vec2 h ) | |
{ | |
vec3 q = abs(p); | |
return max(q.z-h.y,max(q.x*0.866025+p.y*0.5,-p.y)-h.x*0.5); | |
} | |
vec2 scene(vec3 p) | |
{ | |
float floorPlane = p.y + 1.; | |
vec3 rp = p; | |
pModPolar(rp.xz, 12.); | |
float sphere = length(rp*vec3(.9,1,1)-vec3(.3,0,0))-1.; | |
sphere = abs(sphere+.05)-.05; | |
vec3 mirrorP = p; | |
mirrorP.z = -abs(mirrorP.z); | |
// round eyes | |
vec3 mp = p; | |
mp.x = abs(mp.x); | |
float eye = sdSphere(mp, vec3(.3,.4,-1.2), .17); | |
sphere = max(sphere, -eye); | |
// curved mouth | |
float mouth1 = sdSphere(p, vec3(0,.6,-1), 1); | |
float mouth2 = sdSphere(p, vec3(0,1.3,-1), 1.35); | |
sphere = max(sphere, -max(mouth1, -mouth2)); | |
// angular eyes | |
sphere = max(sphere, -sdTriPrism(mp*vec3(1,-1,1)+vec3(-.25,.35,-1.), vec2(.2,1.1))); | |
// both noses | |
sphere = max(sphere, -sdTriPrism(mirrorP-vec3(0,.22,-1.), vec2(.1,1.1))); | |
// angular mouth | |
sphere = max(sphere, -sdTriPrism(mp*vec3(1,-1,1)+vec3(-.37,-.03,-1.), vec2(.16,1.1))); | |
sphere = max(sphere, -sdTriPrism(mp*vec3(1,-1,1)+vec3(-.2,-.04,-1.), vec2(.18,1.1))); | |
sphere = max(sphere, -sdTriPrism(mp*vec3(1,-1,1)+vec3(0,-.05,-1.), vec2(.2,1.1))); | |
floorPlane = -sdBox(p-vec3(0,1,0), vec3(6,2.5,6)); | |
float stem = dot(vec4(rp,1),vec4(1,.1,0,-.2)); | |
stem = max(stem, p.y-1.3); | |
stem = max(stem, -p.y+.95); | |
return vec2( | |
min(floorPlane,min(sphere,stem)), | |
floorPlane < sphere | |
? 0 | |
: sphere < stem | |
? 1 | |
: 2 | |
); | |
} | |
void main(void) | |
{ | |
vec2 uv = vec2(gl_FragCoord.x / v2Resolution.x, gl_FragCoord.y / v2Resolution.y); | |
uv -= 0.5; | |
uv /= vec2(v2Resolution.y / v2Resolution.x, 1); | |
vec3 cam = vec3(0,0,-5); | |
vec3 dir = normalize(vec3(uv,1)); | |
cam.yz = rotate(cam.yz, .3+sin(fGlobalTime*.1)*.1); | |
dir.yz = rotate(dir.yz, .3+sin(fGlobalTime*.1)*.1); | |
cam.xz = rotate(cam.xz, fGlobalTime*.4); | |
dir.xz = rotate(dir.xz, fGlobalTime*.4); | |
float t = 0; | |
for(int i=0;i<100;++i) | |
{ | |
float k = scene(cam+dir*t).x; | |
t += k; | |
if (k<.001) break; | |
} | |
vec3 h = cam+dir*t; | |
vec2 o = vec2(0.001,0); | |
vec3 n = normalize(vec3( | |
scene(h+o.xyy).x-scene(h-o.xyy).x, | |
scene(h+o.yxy).x-scene(h-o.yxy).x, | |
scene(h+o.yyx).x-scene(h-o.yyx).x | |
)); | |
vec2 mat = scene(h); | |
vec3 candlePos = sin(fGlobalTime*vec3( | |
18.1, | |
15.6, | |
14.7 | |
))*.01; | |
if (mat.x > 1.) | |
{ | |
// sky | |
out_color = vec4(0,0,0,1); | |
} | |
else if (mat.y == 0) | |
{ | |
// floor | |
float fakeLight = clamp(1.-length(h)*.12,0,1); | |
vec4 color = vec4(.2,0,.3,0); | |
vec3 fh = fract(h*.5+.501)-.5; | |
float checker = fh.x*fh.y*fh.z; | |
out_color = color*float(checker>0) * fakeLight; | |
} | |
else if (mat.y == 1 || mat.y == 2) | |
{ | |
vec3 fakeN = n; | |
fakeN.xz = rotate(fakeN.xz, -fGlobalTime*.4); | |
// pumpkin | |
vec4 albedo = mat.y == 1 ? vec4(1,.5,0,0) : vec4(.1,.3,.1,1); | |
out_color = albedo * (fakeN.x*.5+.5); | |
out_color += pow(dot(fakeN,normalize(vec3(1,1,-1)))*.5+.5,20.)*.2; | |
} | |
out_color = clamp(out_color, 0,1); | |
bool occluded = false; | |
vec3 lightCheckDir = normalize(candlePos-h); | |
t=0; | |
h += n *.01; | |
h *= .995; | |
float lowestK = 1e9; | |
for(int i=0;i<32&&!occluded;++i) | |
{ | |
float k = scene(h+lightCheckDir*t).x; | |
t += k; | |
lowestK = min(k,lowestK); | |
if (k<0.001) | |
occluded=true; | |
else if (t > distance(candlePos, h)) | |
break; | |
} | |
if(!occluded) | |
out_color += vec4(1,.9,.1,1) * .3 * smoothstep(0.,.02,lowestK); | |
//out_color = vec4(n*.5+.5,0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment