Last active
February 29, 2024 00:54
-
-
Save BarakChamo/bbaa5080acad2e3f8080e3bdd42325a7 to your computer and use it in GitHub Desktop.
Shader distance functions (metrics)
This file contains 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
/* | |
GLSL distance functions and tesselation demo | |
Live demo at: https://www.shadertoy.com/view/4lccW8 | |
*/ | |
/* Euclidean distance */ | |
/* https://en.wikipedia.org/wiki/Euclidean_distance */ | |
float euclideanDistance(float p1, float p2) { | |
float d1 = (p1 - p2); | |
return sqrt(pow(d1, 2.0)); | |
} | |
float euclideanDistance(vec2 p1, vec2 p2) { | |
float d1 = (p1.x - p2.x); | |
float d2 = (p1.y - p2.y); | |
return sqrt(pow(d1, 2.0) + pow(d2, 2.0)); | |
} | |
float euclideanDistance(vec3 p1, vec3 p2) { | |
float d1 = (p1.x - p2.x); | |
float d2 = (p1.y - p2.y); | |
float d3 = (p1.z - p2.z); | |
return sqrt(pow(d1, 2.0) + pow(d2, 2.0) + pow(d3, 2.0)); | |
} | |
/* Manhattan distance */ | |
/* https://en.wikipedia.org/wiki/Taxicab_geometry */ | |
float manhattanDistance(float p1, float p2) { | |
float d1 = abs(p1 - p2); | |
return d1; | |
} | |
float manhattanDistance(vec2 p1, vec2 p2) { | |
float d1 = abs(p1.x - p2.x); | |
float d2 = abs(p1.y - p2.y); | |
return d1 + d2; | |
} | |
float manhattanDistance(vec3 p1, vec3 p2) { | |
float d1 = abs(p1.x - p2.x); | |
float d2 = abs(p1.y - p2.y); | |
float d3 = abs(p1.z - p2.z); | |
return d1 + d2 + d3; | |
} | |
/* Minkowski distance */ | |
/* https://en.wikipedia.org/wiki/Minkowski_distance */ | |
float minkowskiDistance(float p1, float p2, float power) { | |
float d1 = pow(abs(p1 - p2), power); | |
return pow(d1, 1.0 / power); | |
} | |
float minkowskiDistance(vec2 p1, vec2 p2, float power) { | |
float d1 = pow(abs(p1.x - p2.x), power); | |
float d2 = pow(abs(p1.y - p2.y), power); | |
return pow(d1 + d2, 1.0 / power); | |
} | |
float minkowskiDistance(vec3 p1, vec3 p2, float power) { | |
float d1 = pow(abs(p1.x - p2.x), power); | |
float d2 = pow(abs(p1.y - p2.y), power); | |
float d3 = pow(abs(p1.z - p2.z), power); | |
return pow(d1 + d2 + d3, 1.0 / power); | |
} | |
/* Chebyshev distance */ | |
/* https://en.wikipedia.org/wiki/Chebyshev_distance */ | |
float chebyshevDistance(float p1, float p2) { | |
float d1 = abs(p1 - p2); | |
return d1; | |
} | |
float chebyshevDistance(vec2 p1, vec2 p2) { | |
float d1 = abs(p1.x - p2.x); | |
float d2 = abs(p1.y - p2.y); | |
return max(d1, d2); | |
} | |
float chebyshevDistance(vec3 p1, vec3 p2) { | |
float d1 = abs(p1.x - p2.x); | |
float d2 = abs(p1.y - p2.y); | |
float d3 = abs(p1.z - p2.z); | |
return max(d1, max(d2, d3)); | |
} | |
/* Tesselation Demo Fragment Shader */ | |
/* Try this at: shadertoy link */ | |
uniform float uTime; | |
vec2 hash( vec2 p ) { | |
p = vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))); | |
return fract(sin(p)*18.5453); | |
} | |
float random (vec2 st) { | |
return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123); | |
} | |
/* distance tesselation */ | |
vec2 tessellate( in vec2 x, in float wf ) { | |
vec2 n = floor( x ); | |
vec2 f = fract( x ); | |
// weight factor | |
float w = random(n) * wf; | |
// MODIFY THIS: | |
// Maximum distance for distance function | |
// 2.0 and up should cover the whole distance | |
// Less will form distance bubbles | |
vec2 m; | |
m = vec2( 2.0 ); | |
// m = vec2( 0.5 ); | |
// Cover a unit range around the point | |
for( int j=-1; j<=1; j++ ) | |
for( int i=-1; i<=1; i++ ) | |
{ | |
// distance point (edges of the unit square around the point) | |
vec2 g = vec2( float(i), float(j) ); | |
// random point inside the unit square | |
// Basically, random point inside the tile | |
vec2 o = hash( n + g ); | |
// move the point around the tile based on sin(time); | |
vec2 r = g - f + (0.5+0.5*sin(uTime+6.2831*o)); | |
float w = random(o) * wf; | |
// Get the vector's distance from origin | |
// This is similar to the self dot product operation dot(r,r); | |
float d; | |
// MODIFY THIS: try using different functions | |
d = euclideanDistance(vec2(0), r); | |
// d = manhattanDistance(vec2(0), r); | |
d = minkowskiDistance(vec2(0), r, 2.0 + sin(uTime * 2.0)); | |
// d = chebyshevDistance(vec2(0), r); | |
// Additively weight the distance | |
d += w; | |
if( d<m.x ) | |
m = vec2( d, o ); | |
} | |
// Return point distance | |
return m; | |
} | |
out vec4 fragColor; | |
void main() | |
{ | |
vec2 st = vUV.st; | |
// MODIFY THIS: | |
// Tile the coordinate space | |
st *= 5.0; | |
// MODIFY THIS: | |
// Weight factor applied to a random weight coefficient in the tesselation function | |
// https://en.wikipedia.org/wiki/Weighted_Voronoi_diagram | |
float weightFactor = (1.0 + sin(uTime * 5.0)) / 2.0; | |
// Generate tessellate pattern | |
vec2 c = tessellate( st, weightFactor ); | |
// Colorize | |
vec3 col = 0.5 + 0.5 * cos( 2.0 + c.y * 3.0 + c.x + vec3(1.5,0.0,0.0) ); | |
// Add distance-based gradient | |
col *= clamp(1.0 - 0.2 * pow(c.x, 2.0), 0.0,1.0); | |
// Draw points | |
col -= (1.0-smoothstep( 0.01, 0.05, c.x)); | |
fragColor = vec4( col, 1.0 ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment