Добрый вечер. Делаю PathTracer и столкнулся с проблемой:
для расчета теней
прямого освещения я получаю для каждого пикселя его освещенность по формуле:
return emissionColor // RGB(255, 255, 255)
.scale(lightPower - rayLine.getLength() * (lightPower / fadeRadius)) // затухание с увеличением расстояния
.scale(lambertCos); // 0 - 1
В данном коде:
- lightPower - сила источника света (в примере - 2)
- rayLine.getLength() длина луча от точки, для которой рассчитываем освещенность до случайной точки на источнике света (для рассеянных теней)
- fadeRadius - расстояние с которого свет от источника света полностью затухает
lambertCos - рассчитывается по формуле
0 - Vector.dot( // 0 - специально, что бы было заметно отрицательное число
lightDirection, // вектор из точки, для которой рассчитываем освещенность, к источнику света, <b>нормализованный</b>
intersection.getNormal() - нормаль точки, для которой рассчитываем освещенность
);
Возьмем сцену - куб, верхняя плоскость куба - источник света.
С вышеприведенными формулами куб освещается корректно.
Затем возьмем верхнюю плоскость, сожмем её в 2 раза по ширине и длине и опустим, например, до середины куба.
Появится косяк, который виден на изображении - абсолютно резкий переход из тени в свет в точках, расположенных на близком расстоянии к плоскости источника света.
![0a5541a7ac.jpg](http://images.gameru.net/image/direct/0a5541a7ac.jpg)
Что бы это устранить, будем умножать освещенность еще и на угол между направлением луча из точки, для которой рассчитываем освещенность, и нормалью на источнике света.
surfaceCost = Vector.dot(
lightDirection,
shadowRay.getNormal() // нормаль в точке пересечения луча в точке на источнике света
);
return emissionColor // RGB(255, 255, 255)
.scale(lightPower - rayLine.getLength() * (lightPower / fadeRadius)) // затухание с увеличением расстояния
.scale(lambertCos) // 0 - 1
.scale(surfaceCos); // 0 - 1
Результат станет таким, каким нужно, будет выглядеть процентов на 90, как на этой картинке
![cornellBox_matteAndGloss.png](http://web.stanford.edu/~dritchie/path/images/cornellBox_matteAndGloss.png)
На картинке видно, что если источник света не занимает всю поверхность потолка, то он дает легкое затенение на стенах под потолком.
Ну а теперь проблема:
растянем источник света вновь до размеров всего потолка - как результат затенение под источником света все равно останется, т.к. лучи в затененных участках по прежнему будут находиться пол сильным углом к нормали источника света.
Вот как это выглядит (слева сверху)
![f7033290c1.jpg](http://images.gameru.net/image/direct/f7033290c1.jpg)
Я пытался привязать surfaseCos к расстоянию между точкой на поверхности и точкой на источнике света:
surfaseCos = 1 - (surfaseCos * (rayline.getDist() * fadeRadius))
но почему то результат все равно не правильный. На последней картинке, теней на красной стене под ИС быть не должно, а на белой стене они должны появляться сначала резкими, затем становиться все более размытыми, как только ИС начинает удаляться от стены (сужаться), опускаться вниз.
Вообщем - есть у кого какие идеи по моей проблеме?