Skip to content

Instantly share code, notes, and snippets.

@CharStiles
Last active May 11, 2020 14:51
Show Gist options
  • Save CharStiles/efaafb4bc7ad63e8b84db3dcb22003c0 to your computer and use it in GitHub Desktop.
Save CharStiles/efaafb4bc7ad63e8b84db3dcb22003c0 to your computer and use it in GitHub Desktop.
const int step = 128;
const float maxDist = 10.3;
const float smallNumber = 0.02;
// http://www.iquilezles.org/www/articles/palettes/palettes.htm
// As t runs from 0 to 1 (our normalized palette index or domain),
//the cosine oscilates c times with a phase of d.
//The result is scaled and biased by a and b to meet the desired constrast and brightness.
vec3 cosPalette( float t, vec3 a, vec3 b, vec3 c, vec3 d )
{
return a + b*cos( 6.28318*(c*t+d) );
}
float sphere(vec3 pos, float rad){
return length(pos) - rad;
}
// 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 smin( 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 scene(vec3 pos){
vec3 modSpace = vec3(5.,2.,2.);
pos = mod(pos,modSpace) - 1.;
float s = sphere(pos, 0.4);
pModPolar(pos.xy,3.0);
float s2 = sphere(pos +( sin(time)*0.6), 0.2);
return smin(s,s2,(cos(time*2.)+1.)* 0.2);
}
vec3 lookAt(vec2 uv, vec3 camOrigin, vec3 camTarget){
vec3 zAxis = normalize(camTarget - camOrigin);
vec3 up = vec3(0,1,0);
vec3 xAxis = normalize(cross(up, zAxis));
vec3 yAxis = normalize(cross(zAxis, xAxis));
float fov = 2.;
vec3 dir = (normalize(uv.x * xAxis + uv.y * yAxis + zAxis * fov));
return dir;
}
vec3 estimateNormal(vec3 p) {
vec3 n = vec3(
scene(vec3(p.x + smallNumber, p.yz)) -
scene(vec3(p.x - smallNumber, p.yz)),
scene(vec3(p.x, p.y + smallNumber, p.z)) -
scene(vec3(p.x, p.y - smallNumber, p.z)),
scene(vec3(p.xy, p.z + smallNumber)) -
scene(vec3(p.xy, p.z - smallNumber))
);
return normalize(n);
}
float lighting(vec3 origin, vec3 dir, vec3 normal) {
vec3 lightPos = vec3(cos(time)*20., sin(time), 12.);
vec3 light = normalize(lightPos - origin);
float diffuse = max(0., dot(light, normal));
vec3 reflectedRay = 2. * dot(light, normal) * normal - light;
float specular = max(0., (pow(dot(reflectedRay, light), 3.)));
float ambient = 0.05;
return ambient + diffuse + specular;
}
vec4 trace(vec3 camOrigin, vec3 dir){
vec3 ray = camOrigin;
float totalDist = 0.;
float dist;
for(int i = 0 ; i < step; i ++){
dist = scene(ray);
totalDist += dist;
if (dist < 0.001){
vec3 n = estimateNormal(ray);
float l = lighting(ray, dir, n);
vec3 color = cosPalette(totalDist,
vec3(0.5, 0.5, 0.5),
vec3(0.5, 0.5, 0.5),
vec3(1.0, 1.0, 0.5),
vec3(0.80, 0.90, 0.30));
return vec4(color * l, 1.0);
}
if (totalDist > maxDist){
return vec4(0);
}
ray += dist*dir;
}
return vec4(0.0);
}
void main() {
vec2 uv = uv();
// we want to be behind the 0,0,0 point
vec3 camOrigin = vec3(0.0,0.0,-1.0);
// think about the ray origin as the window into the 3D world
vec3 rayOrigin = vec3(uv.x + camOrigin.x,
uv.y + camOrigin.y,
camOrigin.z + 1.0);
vec3 camTarget = vec3(0,sin(time), 2);
vec3 dir = lookAt(uv, camOrigin, camTarget);
vec4 color = trace(camOrigin,dir);
gl_FragColor = color;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment