Pular para o conteúdo
Fundamento · RuídoIntermediário

Movimento browniano fractal (fBm)

Some camadas de ruído com frequência crescente e força decrescente, para ter detalhe em todas as escalas, como em nuvens, terrenos e fumaça.

Como funciona

Uma camada de ruído tem um tamanho só de detalhe: manchas macias, todas mais ou menos do tamanho de uma célula da grade. Formas da natureza têm detalhe em muitos tamanhos ao mesmo tempo. Um litoral tem baías, as baías têm enseadas e as enseadas têm pedras. O movimento browniano fractal, fBm para encurtar, constrói isso somando várias cópias de um ruído, cada uma menor e mais fraca que a anterior. Cada cópia é uma oitava, nome tirado do intervalo musical em que a frequência dobra.

O laço

float fbm(vec2 p) {
    float sum = 0.0;
    float amplitude = 0.5;
    for (int k = 0; k < 5; k++) {
        sum += amplitude * gradientNoise(p);
        p = p * 2.0 + vec2(17.3, 9.1); // dobra a frequência e desloca
        amplitude *= 0.5;              // corta a força pela metade
    }
    return sum;
}

A primeira oitava define as formas grandes. A segunda tem detalhes com metade do tamanho e metade da força, e assim por diante. Cinco oitavas cobrem detalhes de uma unidade até um dezesseis avos de unidade. Como as amplitudes 0.5, 0.25, 0.125… somam menos que 1, a soma fica na mesma faixa de uma oitava do ruído: uns ±0.7 para o ruído de gradiente usado aqui, e em geral mais perto do zero, porque as oitavas raramente atingem o pico juntas.

O deslocamento somado a p impede que as oitavas se alinhem. Sem ele, a grade de cada oitava passa pela origem, e o padrão fica visivelmente mais regular perto de (0, 0). Girar p um pouco entre as oitavas (multiplicando por uma matriz de rotação, veja o fundamento de transformações 2D) vai além e quebra o alinhamento aos eixos que as grades quadradas empilhadas acumulam.

Lacunaridade e ganho

Os dois números do laço têm nome. Lacunaridade é o quanto a frequência cresce por oitava (2.0 aqui). Ganho é o quanto a amplitude encolhe (0.5 aqui). O ganho define a aspereza:

  • 0.5 é o visual clássico, macio mas cheio de detalhe: nuvens, morros.
  • Entre 0.6 e 0.7, as oitavas pequenas continuam fortes, e o resultado fica áspero e granulado: rocha, ferrugem.
  • Por volta de 0.3, as oitavas finas somem rápido, e o resultado fica liso e desfocado.

Uma lacunaridade um pouco fora de 2.0 (1.9 ou 2.1) é um truque comum para que as oitavas nunca se alinhem exatamente. No modelo matemático que dá nome à técnica, o ganho é pow(2.0, -H) para uma lacunaridade de 2, em que H, o expoente de Hurst, mede a aspereza do sinal; terrenos costumam ficar perto de H = 1, ganho 0.5.

Quantas oitavas

Cada oitava custa mais uma chamada de ruído, então o custo cresce linearmente com a quantidade. Oitavas menores que um pixel não acrescentam nada visível e causam cintilação quando o padrão se move, porque o pixel amostra um detalhe fino que não consegue mostrar. Uma boa regra é parar quando os detalhes ficarem menores que uns dois pixels. Com 1080 pixels de largura e um detalhe base de um quarto da tela (270 pixels), isso dá umas oito oitavas; para um fundo quase todo desfocado, três ou quatro bastam.

Cristas e turbulência

Duas variantes mudam o que cada oitava contribui:

float n = gradientNoise(p);
float turbulence = abs(n);           // vales afiados onde o ruído cruza o zero
float ridge = 1.0 - abs(n);          // cristas afiadas no lugar dos vales
ridge *= ridge;                      // elevar ao quadrado afina as cristas

Somado ao longo das oitavas, abs(n) (turbulência) parece fumaça ondulando ou fogo, com vincos onde cada oitava cruza o zero. 1.0 - abs(n), ao quadrado, dá cristas afiadas como cadeias de montanhas ou veios de mármore. Os multifractais de cristas vão um passo além e escalam cada oitava pela anterior, então o detalhe cresce nas cristas e some nos vales, do jeito que a erosão age.

O fBm raramente é a imagem final. Ele é um valor para virar nuvem com um limiar, para passar por uma paleta e virar fogo, para servir de altura num terreno ou para ser realimentado nas próprias coordenadas: esse último caso é a distorção de domínio.

Leitura complementar