Опубликован: 08.07.2007 | Доступ: свободный | Студентов: 1431 / 183 | Оценка: 4.43 / 4.02 | Длительность: 13:47:00
Специальности: Программист
Лекция 7:

Освещенность и материалы. Построения объектов

Реалистичные построения

Принцип текстурирования трехмерных объектов ничем не отличается от двумерного аналога. Для каждой треугольной грани необходимо задать текстурные координаты. Единственное отличие от двумерного варианта заключается в формате вершин и наборе 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);