Delphi World - Direct3D - Добавим немного света
Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
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. В материалах есть одна особенность, они задаются вещественными числами поэтому максимальное значение единица, а минимальное нуль.

Не откомпилированный пример тут

Проект Delphi World © Выпуск 2002 - 2017
Автор проекта: Эксклюзивные курсы программирования