Skip to content

Instantly share code, notes, and snippets.

@CharStiles
Created May 26, 2020 22:13
Show Gist options
  • Save CharStiles/df744c99333dc8bf7a5bacd44266bc6d to your computer and use it in GitHub Desktop.
Save CharStiles/df744c99333dc8bf7a5bacd44266bc6d to your computer and use it in GitHub Desktop.
// Define some constants
const int steps = 128; // This is the maximum amount a ray can march.
const float smallNumber = 0.0001;
const float maxDist = 30.; // This is the maximum distance a ray can travel.
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);
}
void pR(inout vec2 p, float a) {
p = cos(a)*p + sin(a)*vec2(p.y, -p.x);
}
float sdLink( vec3 p, float le, float r1, float r2 )
{
vec3 q = vec3( p.x, max(abs(p.y)-le,0.0), p.z );
return length(vec2(length(q.xy)-r1,q.z)) - r2;
}
float scene(vec3 position){
float ground = position.y + noise(vec3(sin(time/30.),time/4.,time/10.) + position.x *3.) / 1.
- noise((cos(vec3(time/30.)) + position.z*2. -time)) / 1. - (0.+ (pow(length(position),.10)*20.0 )- 20.0);
//) position = mod(position, c) - c*0.5;
float sphere = length(
vec3(
position.x,
position.y - 2.,
position.z)
)-0.99;
vec3 c = vec3(6,2.0,6);
position.y -= time;
position = mod(position,c) - 0.5* c;
position += vec3(0.,1.,0);
float link = sdLink(position, 0.30, 0.3, 0.1);
pR(position.xz,PI/2.);
position -= vec3(0.,1.0,0);
float link2 = sdLink(position, 0.3, 0.3, 0.1);
pR(position.xz,PI/2.);
position -= vec3(0.,1.0,0);
float link3 = sdLink(position, 0.30, 0.3, 0.1);
link = min(min(link,link2),link3);
// We want to return whichever one is closest to the ray, so we return the
// minimum distance.
return smin(link,ground,5.);
}
vec3 estimateNormal(vec3 p) {
float smallNumber = 0.002;
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))
);
// poke around the point to get the line perpandicular
// to the surface at p, a point in space.
return normalize(n);
}
vec4 lighting(vec3 pos, vec3 viewDir){
vec3 lightPos = vec3(cos(time)*0.3,0.8,sin(time)*0.32);
// light moves left to right
vec3 normal = estimateNormal(pos);
float diffuse = dot(normal,lightPos);
vec3 reflectDir = reflect(-lightPos, normal);
vec4 ambient = vec4(hsv2rgb( vec3(((noise(pos.y)*tan(pos.x)*10.)/normal.z )/70.,normal.x,.041)) * 1.91,9.0);
vec3 diffuseCol = hsv2rgb( vec3(((pos.z/3.0)/normal.z )/1.,normal.z,normal.y));
return vec4(diffuse*diffuseCol,1. ) + ambient;
}
vec4 lighting2(vec3 pos, vec3 viewDir){
vec3 lightPos = vec3(cos(time)*0.23,0.3,sin(time)*0.2);
// light moves left to right
vec3 normal = estimateNormal(pos);
vec3 reflectDir = reflect(-lightPos, normal);
float specularStrength =5500.;
vec3 specColor = hsv2rgb( vec3(((noise(pos.y)*tan(pos.x)*10.)/normal.z )/700.,normal.x,.041));
float spec = pow( max(dot(viewDir, reflectDir), -0.80), 6.);
vec3 specular = specularStrength * spec * specColor;
return vec4(specular,1.);
}
vec4 trace2 (vec3 origin, vec3 direction){
float dist = 0.;
float totalDistance = 0.;
vec3 positionOnRay = origin;
for(int i = 0 ; i < steps; i++){
dist = scene(positionOnRay);
// Advance along the ray trajectory the amount that we know the ray
// can travel without going through an object.
positionOnRay += dist * direction;
// Total distance is keeping track of how much the ray has traveled
// thus far.
totalDistance += dist;
// If we hit an object or are close enough to an object,
if (dist < smallNumber * 200.){
// return the lighting
return lighting2(positionOnRay,direction) * (1.-totalDistance/maxDist);
}
if (totalDistance > maxDist){
return vec4(0.); // Background color.
}
}
return vec4(0.);// Background color.
}
vec4 trace (vec3 origin, vec3 direction){
float dist = 0.;
float totalDistance = 0.;
vec3 positionOnRay = origin;
for(int i = 0 ; i < steps; i++){
dist = scene(positionOnRay);
// Advance along the ray trajectory the amount that we know the ray
// can travel without going through an object.
positionOnRay += dist * direction;
// Total distance is keeping track of how much the ray has traveled
// thus far.
totalDistance += dist;
// If we hit an object or are close enough to an object,
if (dist < smallNumber){
// return the lighting
return lighting(positionOnRay,direction) * (1.-totalDistance/maxDist);
}
if (totalDistance > maxDist){
return vec4(0.); // Background color.
}
}
return vec4(0.);// Background color.
}
vec3 lookAt(vec2 uv, vec3 camOrigin, vec3 camTarget){
// we get the z Axis the same way we got the direction vector before
vec3 zAxis = normalize(camTarget - camOrigin);
vec3 up = vec3(0,1,0);
// cross product of two vectors produces a third vector that is
// orthogonal to the first two (if you were to make a plane
// with the first two vectors the third is perpendicular to that
// plane. Which direction is determined by the 'right hand rule'
// It is not communicative, so the order here matters.
vec3 xAxis = normalize(cross(up, zAxis));
vec3 yAxis = normalize(cross(zAxis, xAxis));
// normalizing makes the vector of length one by dividing the
// vector by the sum of squares (the norm).
float fov =2.;
// scale each unit vector (aka vector of length one) by the ray origin
// one for x one for y, there is no z vector so we just add it
// then we finally scale by FOV
vec3 dir = (normalize((uv.x * xAxis) + (uv.y * yAxis) + (zAxis * fov)));
return dir;
}
void main() {
vec2 pos = uv();
pos= pos.xy;
float d = 5.;
vec3 camOrigin = vec3(cos(time/10.) *d, 10.+ sin(time)*0.3,sin(time/10.)*d);
//vec3 camOrigin = vec3(3,3.,sin(time) +2.);
vec3 rayOrigin = vec3(pos + camOrigin.xy, camOrigin.z + 1.);
vec3 target = vec3(0,9. + sin(time/20.)*20.,0);
vec3 dir = lookAt(pos,camOrigin, target);
vec4 color = vec4(trace(rayOrigin,dir)) + vec4(trace2(rayOrigin,dir));
if (color.r < 0.02){
color = texture2D(backbuffer,uvN() + vec2(snoise(vec3(pos*5.,time)) * 0.8 ).yx ) * 0.9 ;
}
gl_FragColor = color;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment