Basic3D Tutorials Основы 3D
Источники света.

 

Типы источников освещения

 

Где бы мы не находились, мы везде можем видеть вещи или какие-то объекты, из-за того, что они освещены, т.е. всегда есть какой-то источник света, но если бы мы не имели источника света, то мы бы ничего не видели. Но ведь это же должно быть и в трехмерном мире? Хорошо, если мы хотим, то мы можем сделать все невидимым, за исключением того, на что воздействует источник света. Первое, что надо сделать, это показать объекты в 3D с плоским заполнением или c заполнением Гуро. Но что, если также хотим показать, освещенные многоугольники, как это сделать? Хорошо, имеются несколько способов реализации источника света, так как есть несколько разных типов источников освещения.

 

Первый, и самый простой, это направленный источник света. Это такой источник освещения, которые не имеет никакого места в пространстве, а свет исходит от него в определенном направлении.

 

Далее, мы имеем точечный источник света. Источник света. Это такой источник света, который имеет место в пространстве (точку), но он не светит в каком-то одном заданном направлении, он светит во всех направлении. Представьте себе светлый огненный шарик, такой же как солонце.

 

Третий тип источника света - прожектор. Это такой источник света, который имеет место в пространстве (точка), направление света и для этого источника задан световой конус. Характеристики конуса задаются углами светового пятна и зоны освещенности. Угол светового пятна определяет конус, в котором интенсивность света максимальна. Угол зоны освещенности определяет конус света с уменьшающейся интенсивностью вокруг светового пятна.

 

Все эти различные типы источников света могут, конечно, иметь их собственные цвета, и Вы можете, конечно, смешивать свет от них на объектах. Далее мы рассмотрим каждый тип источника света в отдельности. Но вначале рассмотрим, как делать рассеянный свет.

 

Рассеянный свет не имеет местоположения или направления. Это даже не источник света, это просто фоновая освещенность сцены. Рассеянный свет характеризуется прежде всего интенсивностью. Интенсивность – это величина от 0 до 1. Если значение 1, то цвет полигона менять не надо. Если 0 – то полигон черный, т.е. не виден. Так же можно задать цвет рассеянного цвета, при этом цвет полигона будет вычисляться как сумма цвета самого полигона и цвета рассеянного цвета умноженного на его интенсивность.

 

Можно так же задать размер области действия рассеянного света и иметь несколько таких, возможно, перекрывающихся областей. При этом можно выключить или включить или плавно менять освещенность таких областей для достижения эффекта включения, выключения света, неисправного освещения.

 

Направленный источник света

 

Направленный источник света - самый простой из источников света. Направленный источник света - только источник света, который светит в одном направлении, и только в одном направлении. Если есть объект, помещенный в середину экрана, и Вы хотите, чтобы на этот объект падал свет из направленного источника света, который расположен справа от объекта, то в этом случае есть очень простой алгоритм для реализации этого.

 

Давайте вычислим вектор, который задает это направление (практически, векторы задают только направление). Если источник света светит справа, то он будет воздействовать на на объекты слева от источника света. Значение этого вектора (1,0,0), так как он задает направление влево. Также имейте в виду, что каждая плоскость на нашем объекте имеет собственную нормаль. Теперь, представьте себе плоскость, нормаль которой указывает прямо против вектора направленного света, то есть лицевая нормаль указывает непосредственно направо (направленный источник света указывает налево). Тогда эта плоскость будет освещена полной интенсивностью света, так как плоскость повернута на нуль градусов от направленного источника света. Когда плоскость повернута на девяносто градусов от света (при этом световые лучи не могут попасть на плоскость), плоскость не получит никакого света вообще. Когда плоскость повернута на 180 градусов от света, то плоскость так же не должна получить свет от источника. Но как мы определяем то, на какой угол нормаль плоскости повернута относительно вектора направленного источника света? Просто, мы знаем формулу скалярного произведения векторов, которая возвращает косинус угла двух векторов:

 

        (Ax*Bx) + (Ay*By) + (Az*Bz) = cos(angle)

 

Теперь, Вы просто можете вычислить угол по этой формуле имея значения векторов A и B. При этом не надо делать арккосинус, чтобы получить точный угол, так как мы знаем, что косинус нуля градусов равняется единице, и косинус 180 градусов равняется минус 1, косинус 90 градусов равняется 0, а косинус минус 90 градусов также равняется 0. Так что мы знаем, что косинус угла должен быть больше чем 0, чтобы плоскость была освещена. Вот что мы должны сделать:

 

Color = ((directional.x * face.normal.x)+

         (directional.y * face.normal.y)+

         (directional.z * face.normal.z))*64

        If (color > 0)

        {

         drawface(color); - фактически интенсивность света, а не сам цвет

        }

 

Мы умножаем цвет на 64, так как это число задает, число градаций цвета на один "чистый" цвет (красный, зеленый или синий). Число мог бы быть больше или меньше, в зависимости от числа оттенков. При этом условие останется тем же, так как интервал будет меняться от -1 до 1, или от -256 до 256.

 

Точечный источник света

 

Точечный источник света имеет место в пространстве, в отличие от направленного источника света. Точечный источник светит во всех направлениях, в отличие от направленного источника света. Но здесь кончаются различия. Алгоритм вычисления интенсивности света, похож на алгоритм вычисления интенсивности для направленного источника света. Представьте себе, что у Вас есть шарик света в вашей комнате. Он сияет во всех направлениях, и свет падает на все объекты, но он не светит на те плоскости, которые повернуты от него. Это очень напоминает ситуацию с направленным источником света, но он светит во всех направлениях.

 

Мы знаем, что направленный источник света светит в одном единственном направлении, а точечный источник света светит во множестве направлений. Поэтому надо вычислить для каждой плоскости вектор направления от нее на такой источник света. Далее вычислить скалярное произведение этого нового направления и нормали к плоскости. Для этого, вычислим вектор от точки источника до средней точки плоскости, и затем нормализуем этот вектор. Вот как это сделать:

 

        Vecx = face.midx - omni.x;

        Vecy = face.midy - omni.y;

        Vecz = face.midz - omni.z;

        Length = sqrt(vecx*vecx + vecy*vecy + vecz*vecz);

        Vecx /= length;

        Vecy /= length;

        Vecz /= length;

 

Теперь, нам осталось найти угол между двумя векторами, нашим новым световым вектором и нормалью к плоскости. Сделать это очень просто, и так же как и для направленного источника света.

 

Прожектор

 

Как уже упоминалось прожектор – это источник света, который имеет местоположение, имеет направление и зону освещенности.

 

Принципиально, вычисление освещенности полигона от прожектора похожее. Так же нужно найти вектор направления на прожектор, как в случае точечного источника света. Затем нужно найти угол между этим вектором и вектором прожектора. Если угол больше, чем угол зоны освещенности, то полигон не получит света от прожектора. Если этот угол меньше, то надо проверить попадает ли полигон в зону максимального света. Если полигон попадает в зону максимального освещения прожектора, то освещенность полигона будет зависеть только от угла между вектором направления на прожектор и вектором освещения самого прожектора.

 

Если полигон не попадает в зону максимального освещения, то интенсивность нужно вычислить на основе разницы между углами максимального освещения и углом направления на полигон. Т.е. если угол направления на полигон равен углу максимального освещения, то коэффициент освещения равен единице, если он равен углу освещения (т.е. там, где свет от прожектора уже не светит), то коэффициент освещения равен нулю.

 

Но все это просто, сложнее то, что нужно вычислять это в каждой точке полигона!!! Почему так? Если мы возьмем достаточно большой полигон и направим на него прожектор, то на полигоне будет пятно света. Но если мы вычислим интенсивность света от полигона только в одной средней точке полигона, то полигон будет иметь везде одинаковую интенсивность. Поэтому при растеризации полигона, необходимо для каждой точки полигона вычислить угол направления на прожектор и определить интенсивность света в этой точке. Конечно же вначале лучше найти такие углы в ребрах задающих полигон, и определить попадает ли вообще такой полигон под прожектор.

 

PMG  3 марта 2005 (c)  Сергей Анисимов