Created
January 20, 2024 22:03
-
-
Save matthewjberger/084ffad115e09c95b70e438be413c723 to your computer and use it in GitHub Desktop.
A little heart shader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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