Skip to content

Instantly share code, notes, and snippets.

@CharStiles
Last active June 6, 2020 18:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CharStiles/663fff8a8346dff52a681c34b4d6d6b7 to your computer and use it in GitHub Desktop.
Save CharStiles/663fff8a8346dff52a681c34b4d6d6b7 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.001;
const float maxDist = 10.; // This is the maximum distance a ray can travel.
float scene(vec3 position){
// So this is different from the normal sphere equation in that I am
// splitting the position into it's three different parts
// and adding a 10th of a cos wave to the x position so it oscillates left
// to right and a (positive) sin wave to the z position
// so it will go back and forth.
float sphere = length(
vec3(
position.x + cos(time)/10.,
position.y,
position.z + (sin(time)+2.))
)-0.5;
// This is different from the ground equation because the UV is only
// between -1 and 1 we want more than 1/2pi of a wave per length of the
// screen so we multiply the position by a factor of 10 inside the trig
// functions. Since sin and cos oscillate between -1 and 1, that would be
// the entire height of the screen so we divide by a factor of 10.
float ground = position.y + sin(position.x * 10.) / 10.
+ cos(position.z * 10.) / 10. + 1.;
// We want to return whichever one is closest to the ray, so we return the
// minimum distance.
return min(sphere,ground);
}
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))
);
// 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 lightPos = vec3(cos(time),0,-1);
// light moves left to right
vec3 normal = estimateNormal(pos);
float mag = dot(normal,lightPos);
// dot is one vector projected onto another,
// when the vectors are similar the dot is stronger
// when the normal is facing the light the mag is
// stronger
return vec4(mag);
}
vec4 march (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);
}
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();
vec3 camOrigin = vec3(0,0,-5);
vec3 rayOrigin = vec3(pos + camOrigin.xy, camOrigin.z + 1.);
vec3 target = vec3(0,sin(time),0);
vec3 dir = lookAt(pos,camOrigin, target);
vec4 color = vec4(march(rayOrigin,dir));
gl_FragColor = color;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment