Освещенность и материалы. Построения объектов
Переключение механизма отсечения граней на противоположный. Теперь необходимо не выводить грани, которые перечислены против часовой стрелки (задние грани). И вызов функции отображения треугольников.
C++ |
device->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); for (int i=0; i<6; i++) { device->SetTexture(0, &textures[i]); device->DrawPrimitive(D3DPT_TRIANGLELIST, i*6, 2); } |
Pascal |
device.SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); for i:=0 to 5 do begin device.SetTexture(0,textures[i]); device.DrawPrimitive(D3DPT_TRIANGLELIST, i*6, 2); end; |
Ниже приведен пример вывода полупрозрачного куба, внутри которого размещена трехмерная модель цветка.
Для придания трехмерной сцене еще большей реалистичности можно добавить тени, которые отбрасывают объекты при освещении их некоторым источником света. Алгоритмы затенения в случае точечных источников света схожи с алгоритмами удаления невидимых поверхностей, с единственным лишь отличием. В алгоритмах удаления невидимых граней определяются поверхности, которые можно увидеть из точки положения наблюдателя, а в алгоритмах затенения выделяются поверхности, которые можно "увидеть" из местоположения источника света. Грани, видимые как из точки наблюдения, так и из источника света, не лежат в тени. Те же поверхности, которые видимы из точки наблюдения, но не видимы из источника света, находятся в тени.
Рассмотрим один из простейших и очень быстрых алгоритмов построения теней. Он предназначен для просчета резких теневых участков от полигональных объектов на ровную поверхность (плоскость). Конечно, этот алгоритм очень ограничен в возможностях, но в то же время он прост для реализации. Основная идея метода заключается в том, что для каждого полигона (треугольной грани) сцены, создается еще один полигон, который будет представлять собой тень первого. Все вершины тени будут находиться в пределах плоскости, на которую производится проекция. Алгоритм построения тени будет содержать следующие шаги:
- Создать луч, начинающийся в источнике света, проходящий через вершину полигона и пересекающий плоскость проецирования;
- Получить (найти) точку пересечения этого луча с плоскостью;
- Проделать шаги 1 и 2 для всех вершин грани, получив таким образом координаты "теневого" полигона и затем отрисовать его обычными методами.
Пусть у нас источник света находится в точке L=(Lx,Ly,Lz), треугольная грань объекта имеет координаты вершин P=(Px,Py,Pz), Q=(Qx,Qy,Qz), R=(Rx,Ry,Rz), а плоскость проецирования (затенения) задается неявным уравнением: Ax+By+Cz+D=0. Требуется определить координаты проекций вершин P,Q,R на плоскость
Обозначим через M=(Mx,My,Mz),N=(Nx,Ny,Nz),O=(Ox,Oy,Oz) - проекции точек P,Q,R соответственно на плоскость
Найдем координаты точки M. Так как точка M лежит на луче, то будет справедливы следующие уравнения
![\left\{ \begin{array}{ccc} Mx=Lx+t(Px-Lx) \\ My=Ly+t(Py-Ly) \\ Mz=Lz+t(Pz-Lz) \end{array} \right,](/sites/default/files/tex_cache/da7d5683e2c7d3618485a0d8f6f69964.png)
С другой стороны точка M лежит в плоскости поэтому верно уравнение: A*Mx+B*My+C*Mz+D=0.
Подставим выражения для Mx,My,Mz в уравнение плоскости: A*(Lx+t(Px-Lx))+B*(Ly+t(Py-Ly))+C*(Lz+t(Pz-Lz))+D=0. Это линейное уравнение относительно параметра t, решая которое находим, что
![t^{.}=-\frac{A*Lx+B*Ly+C*Lz+D}{A(Px-Lx)+B(Py-Ly)+C(Pz-Lz)}.](/sites/default/files/tex_cache/4f60aa8b799d61cba7125a822c5af90c.png)
![t^{.} 0](/sites/default/files/tex_cache/7c1a30435173c84f76e0a1ba6645d85a.png)
![\left\{ \begin{array}{ccc} Mx=Lx+t^{.}(Px-Lx) \\ My=Ly+t^{.}(Py-Ly) \\ Mz=Lz+t^{.}(Pz-Lz) \end{array}\right.](/sites/default/files/tex_cache/91781bc0935c4ef77820751d7da7667a.png)
Аналогичные шаги проделываем для двух других вершин полигона Q и R. Следует заметить, что при вычислении тени на плоскость y=0, параметр .
Рассмотренный метод имеет несколько "подводных камней". Тень будет прорисовываться даже в том случае, если источник света находится между полигоном и плоскостью проецирования или же источник света расположен вообще по другую сторону от плоскости. Поэтому такие ситуации необходимо отслеживать и корректно обрабатывать.
Ниже приводится пример отбрасывания тени от трехмерного объекта (птицы) на плоскость, покрытую текстурой. В одном случае "тень" является непрозрачной, а в другом – прозрачной.
Рассмотрим способ построения ландшафтов и поверхностей средствами библиотеки Direct3D. Данная задача сводится к тому, чтобы на регулярной сетке из треугольников построить трехмерную поверхность (график функции двух переменных, земная поверхность, и т.п.).
Разберем построение трехмерной поверхности, представляющей собой функцию двух переменных y=f(x,z). Пусть для простоты у нас область определения функции f(x,z) ограничена единичным квадратом, т.е. 0<=x<=1, 0<=z<=1. Визуализация рассмотренных поверхностей на растровых устройствах может быть осуществлена путем кусочно-линейной аппроксимации треугольными гранями. Такая триангуляционная поверхность может быть получена следующим образом. Параметрическое пространство x,z (единичный квадрат) дискретизируется по координате x с шагом dx, по координате z – с шагом dz. Для каждой пары значений (x,z) вычисляется точка на поверхности y=f(x,z). Полученный таким образом массив точек триангулируется регулярной сеткой.
Ниже приведены два примера построения трехмерных поверхностей (график функции двух переменных и элементарная поверхность Безье третьей степени) , причем на обе поверхности наложены текстуры.
Разберем один из способов построения ландшафтов, который базируется на так называемой карте высот. Карта высот представляет собой двумерный массив, где каждый элемент (пиксель) определяет высоту точки в сетке треугольников. Как правило, значение высоты ранжируется в диапазоне от 0 до 255. Поэтому для хранения подобных карт высот используют изображения в оттенках серого цвета ( grayscale image ). Более светлые участки на таких изображениях соответствуют более высоким значениям точек, а темные участки определяют низкие значения высот. Кроме этого подбирается текстура, схожая по "характеру" с ландшафтом. Ниже приведен пример построения ландшафта по карте высот.