Created
May 26, 2020 22:13
-
-
Save CharStiles/df744c99333dc8bf7a5bacd44266bc6d 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
// 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