Skip to content

Instantly share code, notes, and snippets.

@BarakChamo
Last active February 29, 2024 00:54
Show Gist options
  • Save BarakChamo/bbaa5080acad2e3f8080e3bdd42325a7 to your computer and use it in GitHub Desktop.
Save BarakChamo/bbaa5080acad2e3f8080e3bdd42325a7 to your computer and use it in GitHub Desktop.
Shader distance functions (metrics)
/*
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