Voronoi
https://gyazo.com/a8e3d070b4dea1fd927e66a516584c11
ボロノイセルラーノイズ
マンハッタンディスタンスボロノイ
https://gyazo.com/9c5298911bbc3b920f9dd426e2f7ae16
https://gyazo.com/4da8cce0b0632357e39f6541f8861abd
ボロノイ図を用いた野立て看板のなわばりモデルの基礎的考察 - 小山 雅明 高橋 由樹 椎塚 久雄 アイワ広告株式会社 株式会社椎塚感性工学研究所
https://gyazo.com/6c4e53bb3465d9ddf45ab1bf696385f2.png
立体錯視(明大博物館@神保町)
砂を掘って巣を作る魚が作る模様のような、自然界に存在するボロノイもある
例えばユークリッド距離を使うのか、マンハッタン距離を使うのかといった、部品選択の違いでボロノイのアルゴリズムにバリエーションがある
3次元にボロノイを拡張すると「結晶」のモデルになる
自分の勢力圏の重心に点を移動してセルを再生成するという操作を繰り返すと整ったボロノイになる
メッシュのリトポでも使えて、この方式を適用するときれいなトポロジになる
円錐を射影してカリングをGPUに任せれば高速にボロノイを描ける
https://gyazo.com/6c4e53bb3465d9ddf45ab1bf696385f2.png
Shader Codes
Unity ShaderGraph
https://gyazo.com/023d0d1031503f05eae3083129ff6dba
https://gyazo.com/4e0c42d88acbc8db9d249ed85e3fc218
GLSL
code:Voronoi.GLSL
// - glslfan.com --------------------------------------------------------------
// Ctrl + s or Command + s: compile shader
// Ctrl + m or Command + m: toggle visibility for codepane
// ----------------------------------------------------------------------------
precision mediump float;
uniform vec2 resolution; // resolution (width, height)
uniform vec2 mouse; // mouse (0.0 ~ 1.0)
uniform float time; // time (1second == 1.0)
uniform sampler2D backbuffer; // previous scene
const float PI = 3.1415926;
vec2 rot(vec2 p, float a){
return vec2(p.x * cos(a) - p.y * sin(a), p.x * sin(a) + p.y * cos(a));
}
// 2D random numbers
vec2 Rand2(vec2 p)
{
return fract(vec2(sin(p.x * 1.32 + p.y * 54.077), cos(p.x * 91.32 + p.y * 9.077)));
}
// voronoi distance noise, based on iq's articles
float Voronoi(vec2 x)
{
vec2 p = floor(x);
vec2 f = fract(x);
vec2 res = vec2(8, 8);
for(int j = -1; j <= 1; j ++)
{
for(int i = -1; i <= 1; i ++)
{
vec2 b = vec2(i, j);
vec2 r = b - f + Rand2(p + b);
// chebyshev distance, one of many ways to do this
float d = max(abs(r.x), abs(r.y));
if(d < res.x)
{
res.y = res.x;
res.x = d;
}
else if(d < res.y)
{
res.y = d;
}
}
}
return res.y - res.x;
}
vec3 hsv(float h, float s, float v){
vec4 t = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(vec3(h) + t.xyz) * 6.0 - vec3(t.w));
return v * mix(vec3(t.x), clamp(p - vec3(t.x), 0.0, 1.0), s);
}
void main(){
vec2 uv = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
vec3 p = vec3(uv, 1.);
p.xy = rot(p.xy, time);
float v = Voronoi(sin(time) * 10. * p.xy);
vec3 col = hsv(cos(time)*v/10., 1., v*dot(p,p));
gl_FragColor = vec4(col, 1.0);
}
code:TechnoVoronoiVinegar.GLSL
// - glslfan.com --------------------------------------------------------------
// Ctrl + s or Command + s: compile shader
// Ctrl + m or Command + m: toggle visibility for codepane
// ----------------------------------------------------------------------------
precision mediump float;
uniform vec2 resolution; // resolution (width, height)
uniform vec2 mouse; // mouse (0.0 ~ 1.0)
uniform float time; // time (1second == 1.0)
uniform sampler2D backbuffer; // previous scene
const float PI = 3.1415926;
vec2 rot(vec2 p, float a){
return vec2(p.x * cos(a) - p.y * sin(a), p.x * sin(a) + p.y * cos(a));
}
// 2D random numbers
vec2 Rand2(vec2 p)
{
return fract(vec2(sin(p.x * 1.32 + p.y * 54.077), cos(p.x * 91.32 + p.y * 9.077)));
}
// voronoi distance noise, based on iq's articles
float Voronoi(vec2 x)
{
vec2 p = floor(x);
vec2 f = fract(x);
vec2 res = vec2(8, 8);
for(int j = -1; j <= 1; j ++)
{
for(int i = -1; i <= 1; i ++)
{
vec2 b = vec2(i, j);
vec2 r = b - f + Rand2(p + b);
// chebyshev distance, one of many ways to do this
float d = max(abs(r.x), abs(r.y));
if(d < res.x)
{
res.y = res.x;
res.x = d;
}
else if(d < res.y)
{
res.y = d;
}
}
}
return res.y - res.x;
}
vec3 hsv(float h, float s, float v){
vec4 t = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(vec3(h) + t.xyz) * 6.0 - vec3(t.w));
return v * mix(vec3(t.x), clamp(p - vec3(t.x), 0.0, 1.0), s);
}
void main(){
vec2 uv = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
vec3 p = vec3(uv, dot(uv,uv));
p.x+=sin(time);
p.y+=sin(p.x*mod(time+30.,60.));
p.xy = rot(p.xy, time);
float v = Voronoi(sin(time) * 10. * p.xy * p.z);
float v2 = Voronoi(.8 * sin(time) * p.xy * p.z);
vec3 col = hsv(cos(time)*v/10., 1., 1.-v*10.);
vec3 col2 = hsv(cos(time)*v2, 1., 1.-v);
gl_FragColor = vec4(mix(col, col2, fract(time)), 1.0);
}
https://gyazo.com/30ac5a7f8f15a966cc11b145242f5c21
code:Voronoi.HLSL
// voronoi distance noise, based on iq's articles
float Voronoi(float2 x)
{
float2 p = floor(x);
float2 f = frac(x);
float2 res = float2(8, 8);
for(int j = -1; j <= 1; j ++)
{
for(int i = -1; i <= 1; i ++)
{
float2 b = float2(i, j);
float2 r = b - f + Rand2(p + b);
// chebyshev distance, one of many ways to do this
float d = max(abs(r.x), abs(r.y));
if(d < res.x)
{
res.y = res.x;
res.x = d;
}
else if(d < res.y)
{
res.y = d;
}
}
}
return res.y - res.x;
}
code:CallVoronoi.HLSL
// to call voronoi
float o = 0.25;
float3 r = float3(o, 0, 0);
float3 g = float3(0, o, 0);
float3 b = float3(0, 0, o);
float v = Voronoi(10 * i.uv);
float3 col = (0, 0, 0);
col = col + step(v, 0.01) * b + step(v, 0.1) * g + step(v, 0.3) * r;
col = col + step(v, 0.01) * b + step(v, 0.1) * g + step(v, 0.3) * r;
col = col + step(v, 0.4) * b + step(v, 0.5) * g + step(v, 0.6) * r;
col = col + step(v, 0.7) * b + step(v, 0.8) * g + step(v, 0.9) * r;
return fixed4(col, 1);
https://gyazo.com/69e2422ffafed6d3504a745029e5afe8
code:FlopinesVoro.GLSL
vec3 voro (vec2 uv)
{
vec2 uv_id = floor (uv);
vec2 uv_st = fract(uv);
vec2 m_diff;
vec2 m_point;
vec2 m_neighbor;
float m_dist = 10.;
for (int j = -1; j<=1; j++)
{
for (int i = -1; i<=1; i++)
{
vec2 neighbor = vec2(float(i), float(j));
vec2 point = rand(uv_id + neighbor);
point = 0.5+0.5*sin(2.*PI*point+time);
vec2 diff = neighbor + point - uv_st;
float dist = length(diff);
if (dist < m_dist)
{
m_dist = dist;
m_point = point;
m_diff = diff;
m_neighbor = neighbor;
}
}
}
m_dist = 10.;
for (int j = -2; j<=2; j++)
{
for (int i = -2; i<=2; i++)
{
if (i==0 && j==0) continue;
vec2 neighbor = m_neighbor + vec2(float(i), float(j));
vec2 point = rand(uv_id + neighbor);
point = 0.5+0.5*sin(point*2.*PI+time);
vec2 diff = neighbor + point - uv_st;
float dist = dot(0.5*(m_diff+diff), normalize(diff-m_diff));
m_point = point;
m_dist = min(m_dist, dist);
}
}
return vec3(m_point, m_dist);
}
code:Voronoi3D.GLSL
vec3 voronoi3d(const in vec3 x) {
vec3 p = floor(x);
vec3 f = fract(x);
float id = 0.0;
vec2 res = vec2(100.0);
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vec3 b = vec3(float(i), float(j), float(k));
vec3 r = vec3(b) - f + hash(p + b);
float d = dot(r, r);
float cond = max(sign(res.x - d), 0.0);
float nCond = 1.0 - cond;
float cond2 = nCond * max(sign(res.y - d), 0.0);
float nCond2 = 1.0 - cond2;
id = (dot(p + b, vec3(1.0, 57.0, 113.0)) * cond) + (id * nCond);
res = vec2(d, res.x) * cond + res * nCond;
res.y = cond2 * d + nCond2 * res.y;
}
}
}
return vec3(sqrt(res), abs(id));
}