Distorção de domínio
Desloque as coordenadas de um ruído com outro ruído, para formas fluidas e dobradas como fumaça, mármore e líquido.
Como funciona
Mover um padrão é mudar a coordenada que você entrega a ele: pattern(p + offset) o desliza, como mostra o fundamento
de transformações 2D. A distorção de domínio (domain warping) usa um deslocamento diferente em cada ponto, e tira esse
deslocamento do próprio ruído. O padrão é empurrado para um lado aqui e para outro ali, e os traços retos se curvam em
redemoinhos e dobras que lembram fumaça, tinta na água, mármore ou lava escorrendo.
O “domínio” é o espaço de entrada de uma função. Distorcê-lo significa deformar o espaço antes que a função o leia, em vez de mudar a função.
Uma distorção
Pegue um fBm, uma soma de oitavasUma camada de ruído numa soma fractal. Cada oitava costuma ter o dobro da frequência e metade da amplitude da anterior, acrescentando detalhes mais finos e mais fracos. Oitava Uma camada de ruído numa soma fractal. Cada oitava costuma ter o dobro da frequência e metade da amplitude da anterior, acrescentando detalhes mais finos e mais fracos.fbm(p) = Σ gainᵏ · noise(lacunarityᵏ · p) de ruído, e calcule-o duas vezes, em dois lugares sem
relação, para ter um vetor 2D aleatório em cada ponto. Some esse vetor, escalado, à coordenada de um terceiro fBm:
vec2 q = vec2(fbm(p), fbm(p + vec2(3.7, 8.1))); // um campo vetorial aleatório e suave
float n = fbm(p + 4.0 * q); // o fBm, lido através da distorção
O deslocamento vec2(3.7, 8.1) só serve para tornar os dois componentes independentes; qualquer deslocamento maior que
algumas células funciona. O 4.0 é a força da distorção: com 0 você recebe o fBm puro de volta, perto de 1 as formas
ondulam, e de 3 a 6 elas se dobram sobre si mesmas. Como q é suave, pixels vizinhos recebem deslocamentos parecidos,
então o resultado também continua suave: o espaço é esticado e dobrado, não rasgado.
Distorcendo a distorção
A ideia se aninha. Distorça o próprio campo vetorial com um segundo nível e leia o fBm final através dele:
vec2 q = vec2(fbm(p), fbm(p + vec2(3.7, 8.1)));
vec2 r = vec2(fbm(p + 4.0 * q + vec2(6.4, 2.9)), fbm(p + 4.0 * q + vec2(1.6, 7.5)));
float n = fbm(p + 4.0 * r);
Cada nível deixa os redemoinhos mais intrincados, com filamentos finos se enrolando uns nos outros. Dois níveis é, em geral, onde para de compensar. O custo sobe rápido: um nível são três chamadas de fBm, dois níveis são cinco e, com cinco oitavas cada, são 25 avaliações de ruído por pixel. Num celular em tela cheia isso pesa; renderize em resolução menor, use menos oitavas nos níveis de dentro (eles só precisam ser suaves, não detalhados) ou grave o resultado numa textura se ele não precisar se mexer.
Cor a partir da distorção
Os vetores intermediários servem para mais do que o valor final. length(q) diz com que força cada ponto foi
empurrado, e r.x e r.y são campos suaves que acompanham as mesmas dobras. Misturar cores com eles, além de com n,
dá o visual riscado e de vários tons do mármore ou das nebulosas:
float tone = clamp(n * 1.5 + 0.5, 0.0, 1.0);
vec3 color = mix(vec3(0.10, 0.12, 0.30), vec3(0.85, 0.45, 0.20), tone);
color = mix(color, vec3(0.95, 0.90, 0.80), clamp(length(q), 0.0, 1.0) * 0.5);
color = mix(color, vec3(0.20, 0.50, 0.55), clamp(abs(r.x) * 2.0, 0.0, 1.0) * 0.4);
Animando
Some o tempo a um dos deslocamentos de dentro, como fbm(p + vec2(3.7, 8.1) + 0.1 * time). O campo de distorção
deriva, e o padrão final se revolve e flui no lugar em vez de deslizar pela tela, o visual de fumaça e nuvens. Somar o
tempo direto a p desliza tudo de uma vez e perde esse efeito.
Distorcendo outras coisas
A coordenada distorcida funciona com qualquer padrão, não só com ruído. Distorça a UV antes de ler uma textura e a imagem ondula como um reflexo na água. Distorça a entrada de listras ou anéis e eles se curvam em veios de mármore ou fibras de madeira. Distorça o ponto passado a um campo de distância e uma forma dura ganha uma borda orgânica. A regra é sempre a mesma: calcule um campo de deslocamento, some-o à coordenada e mantenha a força pequena o bastante para que o resultado ainda se leia como o padrão original.