Эта функция предполагает существование функции noi se3, которая выдает трехмерные значения шума в диапазоне [-1, 1]. Можно попробовать использовать в своей программе реализацию этой функции на языке С от Перлина (http:// www,texturingandmodeling.com/CODE/PERLIN/PERLIN.С). Джон Кессеиич сделал в этом коде несколько изменений (добавил функцию setNoiseFrequency), обеспечивающих плавное изменение значений шума на краях массива. В этом случае при повторении тех же фрагментов (режим GL_REPEAT) переход на краях фрагментов плавный, а не резкий. Измененную версию кода можно найти на веб-сайте этой книги, ;http://3dshaders.com.
Листинг 12.1. Функция на языке С для создания трехмерной текстуры шума
int roise3DTexSize - 128:
GLuint noise3DTexName “ 0;
GLubyte *noise3DTexPtr:
void make3QNoiseTexture(void)
{
i nt f, i, j , k, i nc;
int startFrequency = 4:
int numOctaves = 4;
double ni[3]:
double inci. incj. inck:
int frequency = startFrequency:
GLubyte *ptr: double amp - 0.5;
if ({noise3DTexPtr = (GLubyte *) malloc( noise3DTexSize *
noise3DTexSize * noise30TexSize * 4)) = NULL)
{
fprintf(stderr. "Ошибка: невозможно выделить память\п"); exit(l):
}
for (f = 0. inc = 0: f < numOctaves:
++f. frequency *= 2, ++inc, amp *- 0.5)
{
setNoiseFrequency(frequency): ptr = noise3DTexPtr: ni[0] = ni[1] - ni[2] = 0;
inci = 1.0 / (noise3DTexSize / frequency); for (i - 0: i < noise3DTexSize; ++i. ni[0] += inci)
Листинг 12.1 (продолжение)
{
incj = 1.0 / (noise3DTexSize / frequency):
for (j = 0; j < noise3DTexSize: ++j, ni[ID += incj)
{
inck = 1.0 / (noise3DTexSize / frequency);
for (к = 0; к < noise3DTexSize: ++k. ni[2] += inck, ptr+= 4)
{
*(ptr+inc) = (GLubyte)(((noise3(ni)+1.0) * amp)*128.0):
}
}
}
}
}
Эта функция вычисляет значения шума для четырех октав и сохраняет их в трехмерной текстуре RGBA размером 128 х 128 х 128. Данный код также предполагает, что каждый компонент текстуры сохраняется как 8-битное целое значение. В первой октаве частота равна 4, а амплитуда - 0,5. В самом внутреннем цикле вызывается функция noise3 для получения значения шума, основанного на текущем значении ni. Функция noi se3 всегда возвращает значение в диапазоне [-1, 1]; добавив единицу, получим значение шума в диапазоне [0,2]. Умножив результат на значение амплитуды 0,5, получим значение в диапазоне [0, 1]. И наконец, умножив последнее значение на 128, получим целое число в диапазоне [0, 128], которое'сохраняется в красном компоненте текстуры (при доступе из шейдера это значение будет числом с плавающей запятой в диапазоне [0, 0,5]).
При каждом следующем прохождении цикла частота увеличивается вдвое, а амплитуда вдвое уменьшается. В зеленом компоненте текстуры шума будут сохраняться целые значения из диапазона [0, 64], в синем компоненте - целые значения из диапазона [0, 32], а в компоненте прозрачности - целые значения из диапазона [0, 16]. Изображения, приведенные на рис. 12.5, сформированы отдельно из каждого из этих каналов, после того как значения были приведены к нужному диапазону интенсивности (целые числа в диапазоне [0, 255] или числа с плавающей запятой в диапазоне [0, 1]).