Генерирование псевдослучайных значений шума При данном подходе на этапе инициализации нужно задать постоянный массив noiseTab1e[], состоящий из псевдослучайных значений шума. Длина массива, равная 256, оказалась вполне достаточной, поэтому мы примем именно такую длину.
Теперь основная функция latticeNoised, j, k) просто указывает на массив noiseTable[], что является воспроизводимым. Для того чтобы добиться отсутствия или, по крайней мере, незначительности повторяющихся значений шума при изменении k, в индексирующей функции производится эффективное «перемешивание» значений комбинации k) в пределах от 0 до 255. Это легко сделать с помощью введения второго массива index[], который содержит случайным образом переставленные значения от 0 до 255. (Если бы мы работали, скажем, с массивами длиной 8, то массив index[] содержал бы что-нибудь вроде {3,7,0,1, 6,5,4,2}.) Пичи определил следующие два макроса:
#define PERM(x) index[ (х) & 255]
#define INDEXCix. iy. iz) PERM( (ix) + PERM((iy) + PERM(iz)) )
Макрос PERM принимает целое значение x и выполняет над ним операцию «поразрядное AND», оставляя только восемь младших бит, в результате чего значение х попадает в пределы от 0 до 255. Тогда значение PERM становится равным одному из значений массива индексов. Макрос INDEX трижды использует макрос PERM, чтобы трижды просмотреть массив индексов и в каждом случае выбрать элемент массива index[] на базе одного из трех значений ix, iy, iz. Отметим, что это эффективная и воспроизводимая операция, обеспечивающая достаточную степень перемешивания. Тогда функция latticeNoiseO приобретает следующий простой вид:
float latticeNoiseCint i. int j. int k) {
return noiseTable[ INDEX(i.j.k)]:
}
Разработка класса Noise
Представляется удобным инкапсулировать все вышеописанные действия в класс Noise, который мы будем использовать при генерировании мраморной текстуры, а также других текстур, содержащих шум. На рис. 14.41 приведено объявление этого класса (см. также приложение В).
Листинг 14.11. Генерирование воспроизводимых значений шума