Skip to content

Instantly share code, notes, and snippets.

@CharStiles
Last active June 6, 2020 18:01
Show Gist options
  • Save CharStiles/6df8651a4262c197c7a81b019e65ddec to your computer and use it in GitHub Desktop.
Save CharStiles/6df8651a4262c197c7a81b019e65ddec 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);
}
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 distance the ray had to travel normalized so be white
// at the front and black in the back.
return 1. - (vec4(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();
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 = clamp(color,vec4(0),vec4(0.7));
// just so the white icons at the bottom dont disappear.
// we use clamp to take any whites and bring them down to a
// 0.7 gray
// I will get to making that pull request soon!!
// We are grateful for the force
// lets say it in unison on three
// one
// two
// three
// WE ARE GRATEFUL FOR THE FORCE
}
// 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);
}
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 distance the ray had to travel normalized so be white
// at the front and black in the back.
return 1. - (vec4(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, scale the z axis by the 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(trace(rayOrigin,dir));
gl_FragColor = color;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment