Самоучитель по 3dsmax 7

         

Общий случай можно без особых вычислительных затрат привести к этому упрощенному, как - будет...


Общий случай можно без особых вычислительных затрат привести к этому упрощенному, как - будет рассказано чуть позже. Так вот, в этом случае

intensity = ambient + amp * (N.x * L.x + N.y * L.y + N.z * L.z) =
= ambient + amp * (N.x * 0 + N.y * 0 + N.z * 1) =
= ambient + amp * N.z =
= ambient + amp * sqrt(1 - (N.x * N.x + N.y * N.y)).

То есть интенсивность выражается через N.x, N.y, а эти величины меняются линейно. N.x и N.y у нас - числа с плавающей запятой от -1 до 1 (т.к. длина вектора равна 1), интерполировать их - занятие медленное, да корень считать раз в пиксел тоже не хочется. Поэтому вместо интерполяции N.x и N.y обычно интерполируют, например, 128*(N.x+1) и 128*(N.y+1), причем уже в целых числах. Тогда все возможные значения таким образом отмасштабировнных N.x, N.y - это 0, 1, ..., 255. Поэтому можно заранее посчитать табличку значений intensity для каждой пары отмасштабировнных N.x, N.y.

То есть, мы линейно интерполируем 128*(N.x+1) и 128*(N.y+1) (эти значения меняются тоже линейно, раз N.x, N.y меняются линейно) и по ним по таблице определяем интенсивность. Это и есть текстурирование, только в качестве текстуры используется таблица освещенности размером 256x256 (или любым другим), а в качестве координат текстуры u, v для каждой вершины берутся отмасшатбированные координаты нормали в этой вершине.

Таблица, согласно всего вышеупомянутого, считается так: // ... for (i = 0; i < 256; i++) { for (j = 0; j < 256; j++) { r = pow((i - 128) / 256.0, 2) + // это N.x*N.x pow((j - 128) / 256.0, 2); // это N.y*N.y // длина N меньше 1, поэтому r > 1 быть не может if (r > 1) r = 1; phongTable[i][j] = amp * sqrt(1 - r); } } // ...

Правда, обычно используют другую - нелинейную - таблицу, видимо, хоть для какой-то компенсации всяких ошибок линеаризации...



Содержание раздела