The Code Therapy

The easiest Raymarcher

Raymarcher for all your projects!

Created by mgshadermaster on Tue, 09 Jan 2024 20:33:30 GMT.


#version 300 es
precision highp float;

uniform vec2 resolution;
uniform float time;
uniform vec2 mouselerp;
out vec4 fragColor;

const int rayMarchHalt = 256;
const float rayDistanceMin = 0.001;
const float rayTravelledMax = 2000.0;

// Color Mutation functions

vec3 desiredSkyHue( in float t){

  // Sunset Sky:
  vec3 a = vec3(0.210, 0.058, 0.558);
  vec3 b = vec3(0.373, 0.520, 0.520);
  vec3 c = vec3(0.800, 0.800, 0.500);
  vec3 d = vec3(0.000, 0.200, 0.500);

  vec3 sunset = a + b*cos( 6.28318*(c*t+d) );

  //Nightsky
  a = vec3(0.000, 0.500, 0.500);
  b = vec3(0.000, 0.500, 0.500);
  c = vec3(0.000, 0.500, 0.333);
  d = vec3(0.000, 0.500, 0.667);

//Night Sky
  vec3 nightsky = a + b*cos( 6.28318*(c*t+d));
  return mix(sunset, nightsky, sin(time) * 0.5 + 0.5);
}

// Rotate functions

mat2 rotate2D(float angle){
  return mat2(
    cos(angle), -sin(angle),
    sin(angle), cos(angle)
  );
}

// Sign Distance Field functions

float sdfCylinder(vec3 p, float h, float r, vec3 disp){
  p -= disp;
  vec2 d = abs(vec2(length(p.xz),p.y)) - vec2(r,h);
  return (min(max(d.x,d.y),0.0) + length(max(d,0.0)));
}

float sdfSphere(vec3 point, float radius, vec3 displacement){
  float distance = length(point - displacement) - radius;
  return distance;
}

// Scene Mapper

float sceneMapper(vec3 position){

  vec3 hatPosition = position;
  hatPosition.yz *= rotate2D(time*0.5);
  hatPosition.xy *= rotate2D(time*1.5);
  hatPosition.xz *= -rotate2D(time);
  float hatTop = sdfSphere(hatPosition, 0.6, vec3(0.0, -0.02, 0.0));
  float hatHole = min(sdfSphere(hatPosition, 0.59, vec3(0.0, -0.02, 0.0)), sdfCylinder(hatPosition, 0.6, 0.7, vec3(0.0, -0.62, 0.0)));
  float hatBase = sdfCylinder(hatPosition, 0.01, 1.0, vec3(0.0));
  float hat = min(hatBase, hatTop);
  hat = max(hat, -hatHole);
  return hat;
  return hatHole;
}

// Object UV mapper

vec3 normalMapper(vec3 position){
  float objectDistance = sceneMapper(position);
  vec2 displacement = vec2(0.01, 0.0);
  vec3 objectNormal = objectDistance - vec3(
      sceneMapper(position - displacement.xyy),
      sceneMapper(position - displacement.yxy),
      sceneMapper(position - displacement.yyx)
    );
  return normalize(objectNormal) * 0.5 + 0.5;
}

// Diffuse light Mapper

vec3 diffuseLight(vec3 position, vec3 normal){
  vec3 lightPosition = vec3(0.0, 1.0, 0.0);
  vec3 lightDirection = normalize(position + lightPosition);

  float lightIntensity = max(0.0, dot(lightDirection, normal));
  return lightIntensity * vec3(1.0,0.0,0.0);
}

// Main RayMarcher Loop

void main(void) {
  fragColor = vec4(0.0);
  vec2 vUv = (gl_FragCoord.xy * 2.0 - resolution.xy) / resolution.y;
  vec3 rayOrigin = vec3(0.0,0.0,-2.0);
  //rayOrigin.xz *= rotate2D(time);
  vec3 rayPointing = vec3(vUv.x, vUv.y, 1.0);

  vec3 rayDirection = normalize(rayPointing);

  vec3 objectColor = vec3(0.0);
  float rayTravelled = 0.0;
  int rayMarchIndex = 0;
  for (rayMarchIndex; rayMarchIndex < rayMarchHalt; rayMarchIndex++){
    vec3 rayPosition = rayOrigin + rayDirection * rayTravelled;
    float rayDistance = sceneMapper(rayPosition);
    rayTravelled += rayDistance;
    if (rayDistance < rayDistanceMin){
      vec3 objectNormal = normalMapper(rayPosition);
      objectColor = diffuseLight(rayPosition, objectNormal);
      break;
    }
    if (rayTravelled > rayTravelledMax || rayMarchIndex == rayMarchHalt - 1){
      rayTravelled = 0.0;
      //fragColor = vec4(desiredSkyHue((vUv.y * 0.5 + 0.5) * -1.0 + 1.0), 1.0); // Sky Background

      break;
    }
  }

  // Sculpting Mode
  //fragColor = vec4(vec3(clamp(rayTravelled,0.0,1.0) * 0.5), 1.0);

  // Texturing Mode
  fragColor += vec4(objectColor, 1.0) * vec4(vec3(rayTravelled), 1.0);
}