- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Графика DirectX в Delphi - Михаил Краснов
Шрифт:
Интервал:
Закладка:
var
Vertices : ^TCustomVertex;
hRet : HRESULT;
begin
// Буфер вершин на четыре вершины квадрата
hRet := FD3DDevice.CreateVertexBuffer(4 * SizeOf(TCustomVerrex), 0,
D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, FD3DVB);
if Failed(hRet) then begin
Result := hRet;
Exit;
end;
// Устанавливаем поток
hRet := FD3DDevice.SetStreamSource(0, FD3DVB, SizeOf(TCustomVertex));
if Failed(hRet) then begin
Result := hRet;
Exit;
end;
// Задаем шейдер вершин
hRet := FD3DDevice.SetVertexShader(D3DFVF_CUSTOMVERTEX);
if Failed(hRet) then begin
Result := hRet;
Exit;
end;
// Заполняем буфер данными
hRet := FD3DVB.Lock(0, 4 * SizeOf(TCustomVertex), PByte(Vertices), 0),
if Failed(hRet) then begin
Result := hRet;
Exit;
end;
// Левый нижний угол квадрата
Vertices.X = -0.5; // Координата на листе
Vertices.Y = -0.5;
Vertices.Z = 0; // Левый нижний угол текстуры
Vertices.U = 0;
Vertices.V = 0;
Inc(Vertices); // Переходим к следующей вершине
Vertices.X = -0.5; // Левый верхний угол квадрата
Vertices.Y = 0.5;
Vertices.Z = 0;
Vertices.U = 0;
Vertices.V = 1;
Inc(Vertices);
Vertices.X = 0.5; // Правый нижний угол квадрата
Vertices.Y = -0.5;
Vertices.Z = 0;
Vertices.U = 1;
V ertices.V = 0;
I nc(Vertices) ;
Vertices.X =0.5; // Правый верхний угол квадрата
Vertices.Y = 0.5;
V ertices.Z = 0;
V ertices.U = 1;
V ertices.V = 1;
R esult := FD3DVB.Unlock;
end;
Текстура создается с помощью отдельной функции, единственным аргументом которой является имя файла-прототипа:
function TfrmD3D.InitTexture (const FileName : String) : HRESOLT;
var
hRet : HRESULT;
d3dlr : TD3DLOCKED_RECT; // Вспомогательная запись
dwDstPitch : DWORD; // Шаг поверхности текстуры
X, Y : DWORD;
Bmp : tBitmap;
R, G, В : Byte;
begin
Bmp := TBitmap.Create;
Bmp.LoadFromfile (FileName);
// Создание объекта текстуры
hRet := FD3DDevice.CreateTexture (Bmp.Width, Bmp.Height, 0, 0,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, FD3Texture);
if FAILED(hRet) then begin
Result := hRet;
Exit;
end;
// Запираем поверхность текстуры FD3Texture.LockRect(0, d3dlr, nil, 0);
dwDstPitch := d3dlr.Pitch; // Запоминаем шаг поверхности
// Заполняем поверхность данными из растра
for Y := 0 to Bmp.Height - 1 do
for X := 0 to Bmp.Width - 1 do begin
R := GetRValue (Bmp.Canvas.Pixels [X, DWORD (Bmp.Height - 1) - Y]);
G := GetGValue (Bmp.Canvas.Pixels [X, DWORD (Bmp.Height - 1) - Y]);
В := GetBValue (Bmp.Canvas.Pixels [X, DWORD (Bmp.Height - 1) - Y]);
PDWORD (DWORD(d3dlr.pBits)+Y*dwDstPitch + X * 4)^:=
D3DCOLOR_XRGB(R,G, B);
end;
Bmp.Free;
// Отпираем поверхность текстуры
Result := FD3Texture.UnlockRect(0);
end;
Первые два аргумента метода CreateTexture объекта устройства - ширина и высота создаваемой текстуры. Каждое из этих чисел должно быть степенью двойки. Это очень важное правило, не пропустите его. Растр может быть любого размера, но поверхность текстуры произвольные размеры иметь не может. Если необходимо использовать растр, размеры которого не равны степени двойки, его следует масштабировать, используя те же приемы, которые мы рассмотрели в нескольких примерах на тему применения DirectDraw.
Следующие два параметра метода для нас не важны, а вот на пятый аргумент, формат пиксела, надо обратить внимание. Выбор формата поверхности текстуры оставлен за разработчиком, который сам должен решить, какое значение из предлагаемого набора для него наиболее всего подходит. Для текстур, представляющих собой обычные растры, самым удобным является 32-битный формат, в котором на каждый пиксел приходится четверка чисел. Константа, соответствующая такому формату - D3DFMT_А8R8G8В8. Конечно, можно использовать и другие форматы, например "5-6-5", но при манипуляции с пикселами поверхности необходимо учитывать сделанный выбор.
Последними аргументами метода CreateTexture являются константа, отражающая пожелание разработчика о месте расположения поверхности текстуры, и собственно имя создаваемого объекта.
После того как объект текстуры создан, необходимо заполнить его поверхность. Как видим из кода, порядок действий здесь похож на манипуляции, производимые с поверхностями в DirectDraw: поверхность вначале запирается, и мы получаем информацию о ее шаге и адресе, по которому она располагается. После того как поверхность заполнена, она должна быть разблокирована.
Вторым аргументом метода LockRect, запирающего поверхность текстуры, должна передаваться величина типа ТD3DLОСКЕD_RЕСТ, вспомогательная запись из двух полей: шаг, ширина поверхности и адрес поверхности в памяти.
Заполняем поверхность текстуры тривиальным образом, сообразно с пикселами загруженного растра. Ось Y при этом переворачиваем, присутствующее здесь преобразование типа в DWORD совсем не обязательно, его я осуществляю только для того, чтобы предотвратить ненужные предупреждения компилятора.
Адресация ячейки пиксела текстуры аналогична тому, что мы производили в DirectDraw: опираемся на шаг поверхности, который не обязательно равен ее ширине. Значение X умножается на 4, т. е. на размер одной ячейки. Число это обусловлено выбранным форматом пиксела.
После того как поверхность текстуры заполнена и разблокирована, необходимо задать параметры ее использования и назначить текущей. Из соображений оптимизации рекомендуется устанавливать текстуру только на время непосредственного ее использования:
with FD3DDevice do begin
SetTexture(0, FD3Texture); // Задаем текущую текстуру
SetTextureStageState(0, D3DTSS_COLOROP, D3DTA_TEXTURE);
end;
// Квадрат, покрытый текстурой
hRet := FD3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
if FAILED(hRet) then begin
Result := hRet;
Exit;
end;
// Делаем текстуру недействительной
FD3DDevice.SetTexture(0, nil);
Чтобы задать текущую текстуру, необходимо вызвать метод SetTexture объекта устройства, вторым аргументом передается нужный объект текстуры или nil в случае, если текстура больше не используется. Представленное за этим действие следует понимать как задание правил операций с цветом при работе с текстурой, значение цвета для каждого пиксела определяется содержимым поверхности текстуры.
Методы SetTexture и SetTextureStageState должны вызываться в установленном состоянии воспроизведения, после вызова метода BeginScene. Также помните о том, что блоки установок могут содержать вызовы этих методов.
Итак, текстура является приклеенным к примитиву образом, который масштабируется и поворачивается вслед за ним. В проекте каталога Ех07 квадрат, покрытый текстурой, вращается, а нажатием клавиш <Insert> и <Delete> можно манипулировать его размерами (рис. 8.6).
Поворачивается квадрат тривиальным образом, с течением времени меняем пространственные координаты вершин треугольников, образующих квадрат. Текстурные же координаты вершин неизменны, они не зависят от текущего положения квадрата, этими кнопками мы прикрепляем углы образа к нашему квадрату.
Текстурные координаты
Быстро выводить растровое изображение с помощью DirectDraw мы уже давно научились. Теперь же должны посмотреть все возможности, которые предоставляются нам Direct3D, и то, что сделать раньше мы могли, только затрачивая титанические усилия.
Например, если в предыдущих примерах единичные значения текстурных координат заменить на 3, образ будет повторяться 9 раз. А если и нулевые значения изменить на -3, мы получим 36 образов, уменьшенных в размерах.
Теперь посмотрите проект каталога Ех08. Текстура здесь накладывается на квадрат, образованный четырьмя десятками независимых треугольников: полный круг разделен на четыре четверти, в пределах каждой из которой строится десять независимых треугольников. Первая вершина каждого треугольника - центр итогового квадрата. Остальные вершины лежат на его границе.
Вот часть кода, посвященная верхней четверти квадрата:
for i := 10 downto 1 do begin
Vertices. := 0; // Центр экрана
Vertices.У := 0;
Vertices.Z := 0;
Vertices.U := 0.5; // Центр текстуры
Vertices.V := 0.5;
Inc(Vertices);
// Вершины перечисляем по часовой стрелке,
// движемся с левого верхнего угла квадрата
Vertices.X = 0.5 - i / 10;
Vertices.Y =0.5; // Верхний край, значение Y не меняется
Vertices.Z = 0;
Vertices.U = 1 - i / 10; // Х-координата текстуры
Vertices.V =1.0; // Y-координата текстуры
Inc(Vertices);
Vertices.X =0.5- (i- 1)/10; //По часовой стрелке,
Vertices.Y =0.5; // точка слева
Vertices.Z = 0;
Vertices.U = 1 - (i - 1) / 10;
Vertices.V = 1.0;
Inc(Vertices);
end;
Таким образом, на каждом из сорока треугольников хранится кусочек целого образа, и сложенные рядом, они складывают картинку исходного растра. Включите проволочный режим воспроизведения, чтобы уяснить, как разбивается растр. Кстати, это нам позволит убедиться также в том, что текстуру можно накладывать и на отрезки.
Зачем так сложно сделано, вам станет ясно после знакомства со следующим примером, проектом каталога Ех09, где по нажатии клавиши <Пробел> треугольники разлетаются в разные стороны (рис. 8.7).
Координаты первой вершины всех треугольников, точки разлома картинки, выбираются случайным образом, а на каждый треугольник генерируется свое направление движения:
for i := 10 downto 1 do begin
Vertices.X := CenterX + Radius * Wl [i] ; // Точка разлома картинки
Vertices.Y := CenterY + Radius * Wl [i];
Vertices.Z := 0;
Vertices.U := CenterX + 0.5; // CenterX находится в точке [-0.5; 0.51
Vertices.V := CenterY +0.5;
Inc(Vertices);
// Точки, расположенные на границе квадрата

