Direct3D - Добавим немного света
Автор: Алексей
WEB-сайт: http://daddy.mirgames.ru
Предыдущий пример был не совсем трехмерным. Но в этом примере все будет выглядеть очень даже трехмерным. Для начала разберемся с матрицами. Матрица - это двумерный массив заполнен определенными данными. С помощью матрицы можно перемещать, вращать и масштабировать все примитивы. Для использования матриц в Direct3D есть специальная библиотека DXGUtils, которую надо подключить для использования в нашем приложении.
С помощью матриц можно изменять позицию, с которой вы смотрите. Такая матрица называется видовой, а матрица по изменению угла обзора и дальности виденья называется проекционной. Перед тем как начать работу с матрицами нужно их прописать как переменные.
var
matView, matProj: TD3DMatrix; //Матрица для вида и проекции
matRotateY: TD3DMatrix; //Матрица для вращения
Для прописи мы используем готовый тип из библиотеки DirectXGraphics но на самом деле это все равно, что массив 4 на 4. Бывают матрицы и меньших размеров но их преобразования немного урезаны в возможностях. Еще матрицы можно перемножать. Это делается с целью, чтобы одна матрица, допустим, поворачивала по оси X и Y одновременно. Далее приведены процедуры и функции с матрицами:
function MatrixMul(const a, b: TD3DMatrix): TD3DMatrix;
//функция для перемножения матриц
function SetViewMatrix(var MatrixView: TD3DMatrix;
From, At, Worldup: TD3DVector): HResult;
//устанавливает видовую матрицу
function SetProjectionMatrix(var mat: TD3DMatrix;
fFOV, fAspect, fNearPlane, fFarPlane: Single): HResult;
//устанавливает проекционную матрицу
procedure SetTranslateMatrix(var mat: TD3DMatrix; tx, ty, tz: Single);
overload;
//устанавливает матрицу перемещения
procedure SetScaleMatrix(var mat: TD3DMatrix; sx, sy, sz: Single);
overload;
//устанавливает матрицу масштабирования
procedure SetRotateXMatrix(var mat: TD3DMatrix; fRads: Single);
//устанавливает матрицу вращения по оси Х
procedure SetRotateYMatrix(var mat: TD3DMatrix; fRads: Single);
//устанавливает матрицу вращения по оси Y
procedure SetRotateZMatrix(var mat: TD3DMatrix; fRads: Single);
//устанавливает матрицу вращения по оси Z
Теперь посмотрим, как использовать матрицы. Это не самое сложное и вообще с матрицами проблем не должно быть. Для начала описываете все матрицы, которые хотите использовать в своей программе. Потом устанавливаете каждую, оговаривая, что она должна делать. Вот как делать, чтобы матрицы использовалась:
D3DD.SetTransform(D3DTS_PROJECTION,matProj);
D3DD.SetTransform(D3DTS_VIEW,matView);
D3DD.SetTransform(D3DTS_WORLD,matRotateY);
Первый аргумент этой функции это константа, которая указывает, что за матрицу вы будете использовать. Второй аргумент это сама матрица. И все, дальше нужно рисовать примитивы. Как это делается, смотрите в примере.
Теперь прейдем к освещению. Для создания эффекта освещения нужно задать переменную источника света, потом задать свойства источника света и включить его. Довольно просто, но у каждого источника есть свои особенности. Для использования направленного источника света нужно, всего, задать направление и цвет которым он светит. А у точечного источника света нужно задавать еще коэффициенты закона ослабления. Помимо создания источника света нужно к вершинам указать нормали. Нормаль – это вектор перпендикулярный плоскости имеющий единичную длину. К каждой вершине треугольник нужно задать нормаль для освещения ведь именно по нормалям и рассчитывается освещение. А для того чтобы указать нормаль нам нужно изменить тип и константу нашей вершины. Вот тип и константа из примера:
type
TCUSTOMVERTEX = packed record
X, Y, Z: Single; //Позиция в пространстве
nX, nY, nZ: Single; //Нормаль вершины
end;
const
D3DFVF_CUSTOMVERTEX = D3DFVF_XYZ or D3DFVF_NORMAL;
//Константа для определения параметров вершины
Вот и все что нужно для освещения. Еще в примере я использую материалы. Как вы заметили вершины здесь нельзя окрасить в разные цвета, а материалы это позволяют. Для задания их свойств я использую функцию из библиотеки DXGUtils. В материалах есть одна особенность, они задаются вещественными числами поэтому максимальное значение единица, а минимальное нуль.
Не откомпилированный пример тут
|