Skip to content

Instantly share code, notes, and snippets.

@matthewjberger
Created January 20, 2024 22:03
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 matthewjberger/084ffad115e09c95b70e438be413c723 to your computer and use it in GitHub Desktop.
Save matthewjberger/084ffad115e09c95b70e438be413c723 to your computer and use it in GitHub Desktop.
A little heart shader
// cosine based palette, 4 vec3 params
vec3 palette( in float t )
{
vec3 a = vec3(0.5, 0.1, 0.1);
vec3 b = vec3(0.7, 0.4, 0.4);
vec3 c = vec3(1.0, 0.8, 0.8);
vec3 d = vec3(0.263, 0.416, 0.557);
return a + b*cos( 6.28318*(c*t+d) );
}
float dot2( in vec2 v ) { return dot(v,v); }
float sdHeart( in vec2 p )
{
p.x = abs(p.x);
if( p.y+p.x>1.0 )
return sqrt(dot2(p-vec2(0.25,0.75))) - sqrt(2.0)/4.0;
return sqrt(min(dot2(p-vec2(0.00,1.00)),
dot2(p-0.5*max(p.x+p.y,0.0)))) * sign(p.x-p.y);
}
// The distance estimator for a sphere
float sphereDE(vec3 pos, vec3 spherePos, float size) {
return length(pos - spherePos) - size;
}
vec3 march(vec3 origin, vec3 direction) {
float rayDist = 0.0;
const int NUM_STEPS = 32; // doesn't matter much right now
const float MIN_DIST = 0.001; // threshold for intersection
const float MAX_DIST = 1000.0; // oops we went into space
for(int i = 0; i < NUM_STEPS; i++) {
vec3 current_pos = origin + rayDist*direction;
// Use our distance estimator to find the distance
float _distance = sphereDE(current_pos, vec3(0.0), 1.0);
if(_distance < MIN_DIST) {
// We hit an object! This just adds a subtle shading effect.
return vec3(rayDist/float(NUM_STEPS)*4.0);
}
if(rayDist > MAX_DIST) {
// We have gone too far
break;
}
// Add the marched distance to total
rayDist += _distance;
}
// The ray didn't hit anything so return a color (black, for now)
return vec3(0.0);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = (fragCoord * 2.0 - iResolution.xy ) / iResolution.y;
uv.x += cos(0.5 * iTime * 4.);
uv.y += sin(0.2 * iTime * 4.);
float d = sdHeart(uv * 4.0);
vec3 camPos = vec3(0.0, 0.0, -3.0);
vec3 rayDir = vec3(uv, 1.0);
vec3 col = palette(d + iTime) * march(camPos, rayDir);
d = sin(d * 8. + iTime)/8.;
d = abs(d);
d = 0.004 / d;
d = smoothstep(0.0, 0.1, d);
col *= d;
fragColor = vec4(col, 1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment