Não sigo exatamente o seu código, mas aqui está uma descrição simplificada do algoritmo que atingirá aproximadamente o efeito (com base na imagem que você postou).
A explicação a seguir não é a versão super otimizada, mas é conceitualmente clara (espero). Depois de executá-lo, você pode otimizá-lo (drasticamente, de fato).
- Gere n camadas de ruído aleatório uniforme (apenas pixels em escala de cinza aleatórios).
- Agora experimente cada um deles, amostrando todos os 1, 2, 4, 8, ... 2 ^ (n-1) pixels e interpolando os pixels intermediários. Cada camada é mais lisa que a anterior.
- Agora dimensione-os com um fator de 1, 2, 4, 8, etc. Cada camada é mais escura que a anterior.
- Adicione tudo isso junto.
- Normalize dividindo cada pixel com (1 + 2 + 4 + 8 + ... 2 ^ (n-1)).
O passo difícil é o passo de amostragem e interpolação. Suponha que estamos na camada pulando a amostragem de cada m-ésimo pixel. Aqui está a idéia básica para m> 1 (se m for 1, usamos a imagem como está):
for each pixel x and y
left_sample_coord = m *(x / m) //(integer division, automatically truncated)
right_sample_coord = (left_sample_point + m) % image_width
top_sample_point = m*(y / m)
bottom_sample_coord = (top_sample_point + m) % image_height
horizontal_weight = (x - left_sample_point) / (m - 1)
vertical_weight = (y - top_sample_point) / (m - 1)
sample_top_left = image(left_sample_coord, top_sample_point)
//and the same for the other four corners
//now combine the top two points
top_interpolate = sample_top_left * horizontal_weight + sample_top_right * (1-horizontal_weight)
//now combine the bottom two points
bottom_interpolate = sample_bottom_left * horizontal_weight + sample_bottom_right * (1-horizontal_weight)
//and combine these two last obtained values
smooth_noise(x, y) = top_interpolate * vertical_weight + bottom_interpolate * (1 - vertical_weight)
Algumas dicas:
- O resultado do algoritmo acima pode parecer um pouco desbotado. Você pode reduzir esse efeito usando a mesma camada de ruído para todas as camadas ou melhorar a imagem posteriormente.
- O algoritmo acima usa interpolação linear, mas a interpolação de cosseno (faça uma pesquisa) fornece resultados muito melhores.
- Torne possível observar suas camadas separadamente durante todas as partes do algoritmo. Isso ajudará você a eliminar os bugs rapidamente.