Я не точно следую вашему коду, но здесь приведено упрощенное описание алгоритма, который примерно достигнет эффекта (на основе изображения, которое вы разместили).
Следующее объяснение не является супероптимизированной версией, но концептуально понятно (я надеюсь). После того, как вы запустили его, вы можете оптимизировать его (на самом деле довольно радикально).
- Создайте n слоев равномерного случайного шума (только случайные пиксели в оттенках серого).
- Теперь сэмплируем каждый из них, отбирая каждые 1, 2, 4, 8, ... 2 ^ (n-1) пикселей и интерполируя промежуточные пиксели. Каждый слой более гладкий, чем предыдущий.
- Теперь масштабируйте их с коэффициентом 1, 2, 4, 8 и т. Д. Каждый слой темнее предыдущего.
- Добавьте все это вместе.
- Нормализовать, разделив каждый пиксель с (1 + 2 + 4 + 8 + ... 2 ^ (n-1)).
Сложным шагом является этап выборки и интерполяции. Предположим, что мы находимся в слое, пропускающем выборку каждого m-го пикселя. Вот основная идея для m> 1 (если m равно 1, мы используем изображение как есть):
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)
Несколько советов:
- Результат вышеприведенного алгоритма может показаться немного размытым. Вы можете уменьшить этот эффект, используя один и тот же слой шума для всех слоев, или впоследствии повысить контрастность изображения.
- Приведенный выше алгоритм использует линейную интерполяцию, но косинусная интерполяция (поиск) дает намного лучшие результаты.
- Сделайте возможным просмотр ваших слоев отдельно во всех частях алгоритма. Это поможет вам быстро избавиться от ошибок.