mi_exclusive_lightlist(&n_l, slight, state) ; В итоге указатель ‘light’ хранит в себе полный список источников света, которые нам нужны для просчета.
for (n=0; n < n_l; n++, light++) {…}
Ниже начинается цикл, в котором и происходит сам процесс освещения. Шейдер пробегается по всем источникам света и вызывает следующую функцию, которая уже семплирует источник света (вызывает лайт шейдер).
while (mi_sample_light(&color, &dir, &dot_nl, state, *light, &samples))
Если это Area Light, то функция будет вызвана столько раз, сколько семплов в данном источнике.
Если это простой источник света, то функция вызовется всего один раз. mi_ sample_light возвращает несколько разных значений: цвет света ‘color’, направление к источнику света ‘dir’, результат скалярного произведения ‘dir’ и нормали объекта ‘dot_ nl’ и количество семплов текущего источника света. В принципе, это практически все, что может понадобиться для просчета освещения в данной точке. Дальше используем полученные данные. Именно этот фрагмент, когда влияет на то, как шейдер реагирует на свет.
sum.r += dot_nl * diff->r * color.r;
sum.g += dot_nl * diff->g * color.g;
sum.b += dot_nl * diff->b * color.b; Цвет объекта умножается на цвет света и потом перемножается с dot_.nl, что и создает диффузное освещение.
Если семплов было несколько, то надо будет разделить получившееся значение на значение samples.
Далее вызывается функция mi_compute_irradiance для просчета ненаправленного (indirect) освещения (Final Gather, Global Illumination и Caustic). Данная функция нужна только в том случае, если шейдер должен реагировать на indirect освещение.
Если нам понадобится блик, нужно будет добавить следующие строки внутри функции mi_sam-ple_light, и шейдер превратится из lambert’a в phong:
s = mi_phong_specular(expo, state, &dir);
if (s > 0.0)
{
sum.r += s * spec->r * color.r;
sum.g += s * spec->g * color.g;
sum.b += s * spec->b * color.b;
}
Разумеется, понадобится добавить необходимые параметры и переменные. Полный кол можно посмотреть на диске или в наборе примеров шейдеров, поставляющихся вместе с ментал реем (файл basephong.c).
И так можно наращивать наш шейдер далее, пока он не обзаведется всеми нужными для нас функциями и параметрами. Среди всего можно добавить Reflection, Refraction Ambient и т.д. О возможностях и функциях, которые можно добавить, можно узнать в документации.
Написание mi файлов
С написанием самого кода мы немного разобрались и получили вполне работоспособные шейдера, но как мы помним, шейдер состоит из двух файлов *.dll и *.mi. Вот о создании mi файлов мы поговорим далее.