Ruído celular (Worley / Voronoi)
A distância até o mais próximo de muitos pontos espalhados, para células, escamas, rachaduras e vitrais.
Como funciona
Espalhe pontos pelo plano e pinte cada pixel conforme a distância até o ponto mais próximo. Perto de um ponto fica escuro, e clareia em direção às bordas onde dois pontos estão à mesma distância. As bordas formam um diagrama de Voronoi, o padrão de células que aparece na pele da girafa, na lama seca, na espuma e nos vitrais. Steven Worley descreveu isso como base de texturas em 1996, por isso o ruído também se chama ruído de Worley.
Um ponto por célula
Testar todos os pontos para cada pixel seria lento demais. O truque é colocar exatamente um ponto em cada célula da
grade, num deslocamento aleatório dentro dela, vindo de um hashUma função que embaralha a entrada num valor que parece aleatório, mas é sempre o mesmo para a mesma entrada. Shaders a usam para ter aleatoriedade por pixel e por célula. Hash Uma função que embaralha a entrada num valor que parece aleatório, mas é sempre o mesmo para a mesma entrada. Shaders a usam para ter aleatoriedade por pixel e por célula.h = fract(sin(dot(p, k)) × big) da célula. Assim, o ponto mais
próximo tem de estar na própria célula do pixel ou numa das oito vizinhas, e cada pixel testa nove pontos:
vec2 hash22(vec2 cell) {
uvec2 q = uvec2(ivec2(cell));
// o hash inteiro do fundamento de hash
uint h = mix32(q.x ^ mix32(q.y));
return vec2(h >> 16, h & 0xffffu) / 65536.0; // dois valores em 0..1 de um só hash
}
vec2 cellular(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
float f1 = 8.0; // a menor distância até agora
float f2 = 8.0; // a segunda menor
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
vec2 o = vec2(float(x), float(y)); // qual vizinha
vec2 point = o + hash22(i + o); // o ponto dela, relativo a esta célula
float d = length(point - f);
if (d < f1) {
f2 = f1;
f1 = d;
} else if (d < f2) {
f2 = d;
}
}
}
return vec2(f1, f2);
}
Tudo é medido em relação à célula do pixel ( Vetor Um grupo de dois a quatro números tratado como um só valor (vec2, vec3, vec4). O mesmo tipo guarda uma posição, uma direção, uma cor ou uma UV.f e o), então os números continuam pequenos onde quer que o padrão
esteja. O length das noções de vetoresUm grupo de dois a quatro números tratado como um só valor (vec2, vec3, vec4). O mesmo tipo guarda uma posição, uma direção, uma cor ou uma UV.
Com o ponto em qualquer lugar da célula, um ponto a duas células de distância pode, de vez em quando, estar mais perto
que todos os nove testados, o que aparece como uma emenda reta, curta e rara. Reduzir o deslocamento (0.5 + 0.8 * (hash22(i + o) - 0.5)) mantém os pontos longe das bordas da célula e deixa a emenda bem mais rara, ao preço de um
padrão um pouco mais regular.
O segundo ponto mais próximo cai fora das nove células com muito mais frequência que o mais próximo, então o f2, e
as paredes de F2 − F1 mais abaixo, mostram essas emendas bem mais vezes que o F1. Para visuais baseados no F2, reduza
o deslocamento como acima ou procure num bloco 5×5 (25 células) em vez de 3×3.
F1, F2 e suas combinações
f1 é a distância até o ponto mais próximo, f2 a distância até o segundo mais próximo. Cada um dá uma aparência:
- F1 são manchas escuras com bordas claras: células, bolhas, escamas.
1.0 - f1inverte isso em calombos redondos. - F2 sozinho tem um aspecto mais anguloso e facetado, como cristais ou papel amassado.
- F2 − F1 vale zero exatamente nas bordas entre células e cresce em direção ao meio. Um
smoothstepsobre ele desenha as paredes das células:1.0 - smoothstep(0.0, 0.05, f2 - f1).
F2 − F1 é um substituto barato da distância real até a borda, não a mesma coisa: linhas desenhadas a partir dele ficam mais finas e mais grossas ao longo do comprimento. A distância exata até a borda exige uma segunda passada pelas vizinhas, medindo a distância até a mediatriz entre o ponto mais próximo e cada um dos outros; o artigo sobre bordas de Voronoi nas fontes explica o passo a passo. Use a versão barata para padrões orgânicos e a exata para contornos nítidos e regulares.
Ids de célula
Guarde de qual célula veio o ponto mais próximo e você tem um id por região, a base de vitrais e mosaicos:
vec2 nearest = vec2(0.0);
// dentro do laço, quando um novo mais próximo é encontrado:
// nearest = i + o;
// uma cor aleatória por célula
vec3 tint = vec3(hash22(nearest), hash22(nearest + 7.0).x);
Todos os pixels de uma célula recebem o mesmo id, então a cor é chapada dentro dela e muda nas bordas.
Movimento e variantes
Anime os pontos fazendo cada um oscilar com a própria fase: point = o + 0.5 + 0.4 * sin(time + 6.2831853 * hash22(i + o)). Cada coordenada fica entre 0.1 e 0.9, dentro da célula, então a busca nas nove células falha tão raramente quanto
com o deslocamento reduzido acima. Usar outra distância muda o formato das células: a distância de Manhattan
(abs(d.x) + abs(d.y)) e a de Chebyshev (max(abs(d.x), abs(d.y))) dão células com paredes retas na horizontal, na
vertical e na diagonal, com um ar mais mecânico. A versão 3D testa 27 células e dá os mesmos padrões na superfície de
qualquer malha, sem precisar de UVs.