5.2.Настройки освещения Из предыдущего раздела ясно, что для расчета освещения в вершине необходимы следующие данные:
нормаль в вершине,
свойства поверхности,
свойства источников света, освещающих данный объект.
Рассмотрим их в указанном порядке.
Чтобы задать нормаль к поверхности в вершине следует добавить ее в структуру вершины и указать соответствующий FVF флаг (D3DFVF_NORMAL). В вершине нормаль идет всегда после позиции и перед diffuse.
struct Vertex
{
float x, y, z;
float nx, ny, nz;
DWORD color;
};
Следует обратить внимание на то, что нормаль должна иметь единичную длину (быть нормализованной). В противном случае скалярное произведение будет изменяться в интервале отличном от [-1, 1], что не предполагается моделью освещения. Вышесказанное относится к случаю, когда мировая матрица не содержит масштабирования. В противном случае длина нормали напрямую зависит от масштабирования, и для корректного расчета освещения следует включать нормализацию нормалей после трансформации в камерную систему координат (настройка D3DRS_NORMALIZENORMALS). Это относительно не дешевая, но необходимая операция. Также ее следует включать в случае неортогональных осей мировой матрицы (редкий, но встречающийся в практике случай).
Свойства поверхности (другими словами, свойства материала) задаются в структуре D3DMATERIAL9 и устанавливаются вызовом SetMaterial(). D3DMATERIAL9 содержит цвета Ambient, Diffuse, Specular, Emissive и значение степени для отраженного (specular) освещения – Power. Следует обратить внимание, что в результате расчета освещения альфа-компонента результата равна Diffuse.а.
Свойства источников света задаются в структуре D3DLIGHT9:
typedef struct _D3DLIGHT9 {
D3DLIGHTTYPE Type; // Тип источника света
D3DCOLORVALUE Diffuse; // Diffuse цвет источника
D3DCOLORVALUE Specular;// Specular цвет источника
D3DCOLORVALUE Ambient; // Ambient цвет источника
D3DVECTOR Position; // Позиция источника (для point и spot)
D3DVECTOR Direction; // Направление источника (для directional и
// spot)
float Range; // Радиус влияния источника (за его пределами
// освещение = 0) (для point и spot)
float Falloff; // Значение степени управляющей затуханием
// конусного источника света по углу,обычно
// выбирается равным 1.
float Attenuation0; // Коэфф. A0 затухания point и spot источников
float Attenuation1; // Коэфф. A1 затухания point и spot источников
float Attenuation2; // Коэфф. A2 затухания point и spot источников
float Theta; // Внутренний угол конусного источника света (в рад)
float Phi; // Внешний угол конусного источника света (в рад)
} D3DLIGHT9;
Необходимо обратить внимание на то, что следует заполнять все необходимые (для данного типа источника) поля структуры D3DLIGHT9. Например, не заполнение Attenuation0 - Attenuation2 приведет к тому, что они по умолчанию могут оказаться нулями, что в свою очередь приведет к делению на 0 при расчете затухания по расстоянию. При этом поведение видеокарт (и их драйверов) может разниться. Если для NVidia карт это может оказаться приемлемым, то ATI карты при задании таких коэффициентов просто игнорируют источник. Чтобы отловить такого рода ошибки на стадии разработки программы, следует пользоваться отладочной версией Direct3D (см. раздел 9.2).
Теперь рассмотрим, каким образом в Direct3D осуществляется задание активных источников света. В отличие от остальных структур (например, вершинного буфера) источники света не создаются. Значения их параметров устанавливаются для определенного индекса методом SetLight(DWORD Index, CONST D3DLIGHT9 *pLight9). После этого источник света можно включить (и выключить) используя LightEnable(DWORD Index, BOOL bEnable). В реальных приложениях далеко не все объекты освещаются всеми источниками света. Поэтому, если нет никакой информации о группировке объектов по источникам света, то следует перед рендерингом освещаемого объекта выключать источники, освещавшие предыдущий, и включать источники, влияющие на текущий.
В разделе 5.1 упоминалось, что существуют два режима освещения – без учета отраженной компоненты и с ее учетом. Чтобы включить specular освещение следует с помощью метода SetRenderState() установить настройку D3DRS_SPECULARENABLE в TRUE.
|