Результаты выглядят действительно получше. Считается она так: // ... for (i = 0; i < 256; i++) for (j = 0; j < 256; j++) phongTable[i][j] = amp * pow(sin(i * PI / 256) * sin(j * PI / 256), 4); // ...
Для полного комплекта осталось только привести кусочек кода по вычислению координат в этой таблице: // ... len = N.x * N.x + N.y * N.y + N.z * N.z; N.x /= len; // на случай, если длина N не равна 1 N.y /= len; N.z /= len; u = (1 + N.x) * 128; // собственно расчет координат v = (1 + N.y) * 128; // ...
Теперь вернемся к вопросу о том, как привести случай с произвольным вектором освещения к только что рассмотренному, где L = (0,0,1). Здесь все вроде бы просто. Просто применим к нормалям в вершинах любой поворот, совмещающий наш произвольный вектор света с вектором (0,0,1). Скалярное произведение при этом не изменяется, поэтому так делать можно. Ну, а после этого поворота уже имеем только что расписанный упрощенный случай.
Этот поворот нормалей в каждой вершине не требует практически никаких затрат по следующей причине. Поворот сам по себе, конечно, достаточно медленная процедура и процессорное время отъедает. Но при движении и вращении камеры и объекта мы все равно должны будем соответственно поворачивать нормали. Так вот, эти два поворота можно совместить в один. Если использовать матрицы, все это делается совсем просто - достаточно перемножить (в нужном порядке!) матрицу собственного поворота объекта, матрицу перехода от произвольной камеры к нашей "стандартной" камере и матрицу перехода от произвольного вектора света к "стандартному" вектору света (0,0,1). Т.