Освещенность и материалы. Построения объектов
Реалистичные построения
Принцип текстурирования трехмерных объектов ничем не отличается от двумерного аналога. Для каждой треугольной грани необходимо задать текстурные координаты. Единственное отличие от двумерного варианта заключается в формате вершин и наборе FVF флагов.
C++ |
struct VERTEX3D { FLOAT x, y, z; FLOAT u, v; }; #define MY_FVF (D3DFVF_XYZ | D3DFVF_TEX1); ... VERTEX3D points[3] = { { -1.0f,-1.0f, 0.0f, 0.0f, 1.0f, }, { 0.0f, 1.0f, 0.0f, 0.5f, 0.0f, }, { 1.0f,-1.0f, 0.0f, 1.0f, 1.0f, } } |
Pascal |
type Vertex3D = packed record x, y, z: Single; u, v: Single; end; const MY_FVF = D3DFVF_XYZ or D3DFVF_TEX1; var points: array [0..2] of Vertex3D = ( (x: -1; y: -1; z: 0; u: 0; v: 1), (x: 0; y: 1; z: 0; u: 0.5; v: 0), (x: 1; y: -1; z: 0; u: 1; v: 1) ); |
Ниже показан пример вывода куба, у которого все грани покрыты различными текстурами. Для этого можно объявить массив для хранения текстур из шести элементов типа IDirect3DTexture9.
C++ |
LPDIRECT3DTEXTURE9 textures[6]; LPCSTR files[] = { {"bricks.bmp"}, {"colors.bmp"}, {"Lake.bmp"}, {"stone_wall.bmp"}, {"wall.bmp"}, {"fur.jpg"} }; ... for (int i=0; i<6; i++) D3DXCreateTextureFromFile( device, files[i], &textures[i] ); |
Pascal |
var textures: array [0..5] of IDirect3DTexture9; files: array [0..5] of AnsiString = ( ('bricks.bmp'), ('colors.bmp'), ('Lake.bmp'), ('stone_wall.bmp'), ('wall.bmp'), ('fur.jpg') ); ... for i:=0 to 5 do D3DXCreateTextureFromFile(device, PChar(files[i]), textures[i]); |
Теперь если куб у нас храниться в виде 12 независимых треугольных граней, то его вывод может быть осуществлен с помощью следующего кода.
C++ |
for (int i=0; i<6; i++) { device->SetTexture(0, &textures[i]); device->DrawPrimitive(D3DPT_TRIANGLELIST, i*6, 2); } |
Pascal |
for i:=0 to 5 do begin device.SetTexture(0, textures[i]); device.DrawPrimitive(D3DPT_TRIANGLELIST, i*6, 2); end; |
Ниже приведены примеры (кадры анимации) вращения такого куба.
Рассмотрим один из способов построения полупрозрачных трехмерных объектов. Данный метод прозрачности применим только для выпуклых объектов. Идея его заключается в следующем. Вначале выводятся те грани объекта, которые считаются невидимыми для наблюдателя (задние грани). Затем включается режим полупрозрачности (смешивания цветов). Выводим грани объекта, которые видны наблюдателю. Отображение "передних" и "задних" для наблюдателя сторон объекта можно осуществить с помощью механизма отсечения граней. Предположим, что вершины грани перечислены по часовой стрелке. Тогда отключение вывода таких граней отобразит нам "задние" стороны примитива (в нашем случае куба). Программно этот шаг может выглядеть так.
C++ |
device->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW ); 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_CW); for i:=0 to 5 do begin device.SetTexture(0,textures[i]); device.DrawPrimitive(D3DPT_TRIANGLELIST, i*6, 2); end; |
Ниже показан пример вывода "внутренних" сторон куба.
Включение полупрозрачности с нужными параметрами смешивания цветов.
C++ |
device->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR ); device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR ); |
Pascal |
device.SetRenderState(D3DRS_ALPHABLENDENABLE, 1); device.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR); device.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR); |