Ruído de valor
Coloque um valor aleatório em cada canto de uma grade e misture entre eles, para ter uma aleatoriedade suave que varia pelo espaço.
Como funciona
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. Ruído Uma função pseudoaleatória e suave da posição. Valores ou gradientes aleatórios ficam numa grade e são misturados entre os pontos, então pontos próximos recebem valores parecidos e o resultado não tem padrão visível.h = fract(sin(dot(p, k)) × big) dá a cada entrada um valor sem relação com o vizinho, então pixels lado a lado saltam do
escuro para o claro ao acaso. A maioria das coisas da natureza não é assim: uma nuvem, uma mancha ou a superfície de
uma rocha variam suavemente de um ponto para o outro e só parecem aleatórias numa escala maior. O
ruídoUma função pseudoaleatória e suave da posição. Valores ou gradientes aleatórios ficam numa grade e são misturados entre os pontos, então pontos próximos recebem valores parecidos e o resultado não tem padrão visível.
Cantos e mistura
Separe a posição em célula e posição dentro da célula, a mesma divisão com floor e fract usada no ladrilhamento.
Cada um dos quatro cantos da célula recebe um valor aleatório do hash. O valor do pixel é uma mistura dos quatro,
ponderada pela proximidade de cada um:
float valueNoise(vec2 p) {
vec2 i = floor(p); // o canto inferior esquerdo da célula
vec2 f = fract(p); // onde o pixel está dentro da célula, 0..1
float a = hash21(i); // inferior esquerdo
float b = hash21(i + vec2(1.0, 0.0)); // inferior direito
float c = hash21(i + vec2(0.0, 1.0)); // superior esquerdo
float d = hash21(i + vec2(1.0, 1.0)); // superior direito
vec2 u = f * f * (3.0 - 2.0 * f); // transição do smoothstep, por eixo
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
}
Os dois Interpolação linear (mix) Mistura de a até b por um fator t, em linha reta. O GLSL chama de mix; o HLSL e a maioria dos editores de nós chamam de lerp.mix de dentro misturam ao longo de x nas bordas de baixo e de cima, e o de fora mistura esses dois resultados
ao longo de y. Isso é interpolação bilinear, feita com mixMistura de a até b por um fator t, em linha reta. O GLSL chama de mix; o HLSL e a maioria dos editores de nós chamam de lerp.mix(a, b, t) = a (1 − t) + b thash21 é o hash de seno do
fundamento de hash; qualquer hash que leve uma célula a 0..1 serve. Células vizinhas compartilham os cantos, então o
resultado é contínuo nas bordas: um pixel na borda recebe os mesmos dois valores de canto pelos dois lados.
A escala de p define o tamanho dos detalhes. valueNoise(uv * 8.0) tem umas oito manchas de um lado a outro da
tela; uv * 40.0 deixa o ruído fino.
Por que a curva de transição
Misturar com Smoothstep Um limiar suave. Vale 0 abaixo da primeira borda, 1 acima da segunda e segue uma curva em S com as pontas planas entre elas.f direto é interpolação linear. Ela é contínua, mas a inclinação dá um salto em toda borda de célula, e
o olho percebe esses vincos como uma grade apagada de linhas retas e losangos. Passar o f antes por
f * f * (3.0 - 2.0 * f), a mesma cúbica que o smoothstepUm limiar suave. Vale 0 abaixo da primeira borda, 1 acima da segunda e segue uma curva em S com as pontas planas entre elas.t = clamp((x − e0) / (e1 − e0), 0, 1); s = t² (3 − 2t)
A segunda derivada da cúbica ainda salta nas bordas. Numa cor chapada isso é invisível, mas aparece quando o ruído vira altura e recebe luz, porque a iluminação depende da inclinação e da rapidez com que ela muda. A transição quíntica resolve isso, ao custo de mais umas multiplicações:
vec2 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0); // 6f⁵ − 15f⁴ + 10f³
Use a cúbica para cores e máscaras, e a quíntica quando o ruído virar geometria ou normal.
Como ele fica, e seus limites
O ruído de valor vai de 0 a 1, embora valores perto das pontas sejam raros, porque exigem quatro cantos perto da mesma ponta. Ele fica macio e um pouco quadriculado: as manchas claras e escuras ficam nos cantos da grade e, se você procurar, dá para ver o alinhamento dela. Isso é aceitável numa máscara de dissolve, num tremular ou em qualquer coisa que se mexa, e ele é o ruído mais barato que existe: quatro hashes e três mixes.
Quando a grade aparece, a solução de sempre é o ruído de gradiente, o próximo fundamento, que esconde melhor a grade com um pouco mais de conta. Somar várias cópias em escalas diferentes de qualquer um dos dois dá o detalhe mais rico do fBm.
Usando
O ruído é um valor de 0 a 1, então se encaixa em tudo dos fundamentos de funções de forma. Aplique um limiar com
smoothstep para fazer manchas, compare com um valor que se move para uma revelação ou use-o num mix entre duas
cores:
float n = valueNoise(uv * 6.0);
// uma borda suave que avança conforme progress sobe
float mask = smoothstep(progress - 0.05, progress + 0.05, n);
vec3 color = mix(vec3(0.1, 0.3, 0.1), vec3(0.4, 0.6, 0.2), n);
Anime movendo a entrada (uv * 6.0 + vec2(time * 0.2, 0.0) faz o ruído deslizar) ou misturando dois campos de ruído
ao longo do tempo. Somar o tempo a um só eixo de um ruído 2D apenas desliza o padrão; para um ruído que muda no lugar,
você precisa de um ruído 3D com o tempo como terceiro eixo, que funciona do mesmo jeito, com oito cantos em vez de
quatro.