float random( vec2 uv ) 
{
  return fract( sin( dot( uv.xy, vec2( 12.9898, 78.233 ) ) ) * 43758.5453123 );
}


float worley( vec2 uv, float columns, float rows ) 
{
	
	vec2 index_uv = floor( vec2( uv.x * columns, uv.y * rows ) );
	vec2 fract_uv = fract( vec2( uv.x * columns, uv.y * rows ) );
	
	float minimum_dist = 1.0;  
	
	for ( int y= -1; y <= 1; y++ ) 
  {
		for ( int x= -1; x <= 1; x++ ) 
    {
			vec2 neighbor = vec2( float( x ), float( y ) );
			vec2 point = random( index_uv + neighbor );
			
			vec2 diff = neighbor + point - fract_uv;
			float dist = length (diff );

			minimum_dist = min( minimum_dist, dist );
		}
	}
	
	return minimum_dist;
}

vec2 voronoi( vec2 uv, float columns, float rows ) 
{	
	vec2 index_uv = floor( vec2( uv.x * columns, uv.y * rows ) );
	vec2 fract_uv = fract( vec2( uv.x * columns, uv.y * rows ) );
	
	float minimum_dist = 1.0;  
	vec2 minimum_point;

	for ( int y= -1; y <= 1; y++ ) 
  {
		for ( int x= -1; x <= 1; x++ ) 
    {
			vec2 neighbor = vec2( float( x ), float( y ) );
			vec2 point = random( index_uv + neighbor );

			vec2 diff = neighbor + point - fract_uv;
			float dist = length( diff );
  
			if ( dist < minimum_dist )
      {
				minimum_dist = dist;
				minimum_point = point;
			}
		}
	}


	return minimum_point;
}