#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);
}