- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Графика DirectX в Delphi - Михаил Краснов
Шрифт:
Интервал:
Закладка:
D3DFVF_CUSTOMVERTEX = D3DFVF_XYZ or D3DFVF_NORMAL or D3DFVF_DIFFUSE;
При заполнении буфера вершин цветовая составляющая заполняется только для треугольников сферы и конуса. Для треугольников, образующих комнату, значение диффузной составляющей вершин остается нулевым. Вы можете оптимизировать подобные моменты и использовать отдельные форматы вершин.
Материалы для стен, конуса и сферы инициализируются точно так же, как в первоначальном примере, но при обычном воспроизведении необходимо обязательно указать, что окрашивание треугольников производится с учетом текущего установленного материала, а не значения диффузной составляющей их вершин:
with FDSDDevice do begin
SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
SetRenderState(D3DRS_AMBIENT, $00202020);
SetRenderState(D3DRS_LIGHTING, Dword (True));
SetRenderState(D3DRS_NORMALIZENORMALS, DWORD (True));
// Явно указываем использование материала
SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
end;
При движении курсора мыши по поверхности окна отслеживаются его координаты:
var
OX, OY : DWORD;
procedure TfrmD3D.FormMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
begin
OX := X;
OY := Y; end;
Вы можете оптимизировать часть кода, связанную с определением позиции, ведь для получения положение курсора в любой момент времени можно использовать функцию GetCursorPos.
Помимо функции Render, я ввел функцию укороченного воспроизведения, которая отображает сцену с измененными установками и не заканчивается переключением буферов:
function TfrmD3D.Draw : HRESULT;
var
hRet : HRESULT;
begin
if FD3DDevice = nil then begin
Result := E_FAIL;
Exit;
end;
// Очищаем только Z-буфер
hRet := FD3DDevice.Clear(0, nil, D3DCLEAR_ZBUFFER, 0, 1.0, 0);
if FAILED(hRet) then begin
Result := hRet;
Exit;
end;
hRet := FD3DDevice.BeginScene;
if FAILED(hRet) then begin
Result := hRet;
Exit;
end;
with FD3DDevice do begin
SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
// Работа с освещением запрещена
SetRenderState(D3DRS_LIGHTING, Dword (False));
end;
DrawScene; // Рисуем комнату
Result := FD3DDevice.EndScene;
end;
При отключенном освещении стены комнаты будут выглядеть черными. Поэтому нам незачем тратить время для очистки цветового буфера. Здесь I также можно оптимизировать код, воспроизводить только те объекты, между (которыми будет осуществляться выбор, и не тратить время на воспроизведение объектов фона. В таком случае потребуется, конечно, очищать цветовой буфер.
Чтобы увидеть, каким остается содержимое заднего буфера после работы этой функции, можете дополнить ее строкой переключения буферов. После щелчка кнопки мыши вы увидите такую же картинку, как на рис. 10.5.
При щелчке кнопки мыши получаем доступ к заднему буферу, запираем полученную поверхность и анализируем содержимое нужного пиксела:
procedure TfrmD3D.FormClick(Sender: TObject);
var
Back : IDirect3DSurface8; // Поверхность заднего буфера
d3dlr : TD3DLOCKED_RECT;
dwDstPitch : DWORD;
hRet : HRESULT;
DWColor : DWORD;
R, G, В : Byte;
begin
R := 0; // Инициализация для предотвращения предупреждений компилятора
G := 0;
В := 0;
FActive := False; // Перерисовку кадра временно отменяем
Back := nil;
hRet := Draw; // Рисуем упрощенный вариант сцены, в задний буфер
if Failed (hret) then ErrorOut ('Draw', hRet); // Получаем доступ к заднему буферу
hRet := FDSDDevice.GetBackBuf fer (0, D3DBACKBUFFER_TYPE_MONO, Back) ;
if Failed (hret) then ErrorOut ( 'GetBackBuf fer ' , hRet); // Обнуляем поля вспомогательной структуры
ZeroMemory (@d3dlr, SizeOf (d3dlr) ) ; // Поверхность заднего буфера запирается
hRet := Back.LockRect (d3dlr, nil, D3DLOCK__READONLY) ;
if Failed (hret) then ErrorOut {'LockRect', hRet); // Значение смещения при выравнивании поверхности
dwDstPitch := dSdlr. Pitch;
case d3ddm. Format of // Текущий формат рабочего стола
D3DFMT_X8R8G8B8 : begin // 32-битный RGB
// Пиксел, соответствующий позиции курсора
DWColor := PDWORD (DWORD (d3dlr .pBits) + OY *
dwDstPitch + OX * 4)A; // Цветовые веса пиксела
R := (DWColor shr 23) and $lf;
G := (DWColor shr 7) and $lf;
В := DWColor and $lf;
end;
D3DFMT_R5G6B5 : begin // 16-битный 5-6-5
DWColor := PDWORD (DWORD (d3dlr .pBits) + OY *
dwDstPitch + OX * 2)^;
R := (DWColor shr 11) and $lf;
G := (DWColor shr 5) and $3f;
В := DWColor and $lf;
end;
end;
Back.UnLockRect; // Возможное исключение не обрабатывается
if Assigned (Back) then begin // Удаляем поверхность
Back._Release;
Back := nil;
end;
// Интерпретация результата
if В о 0 then ShowMessage ('Выбран конус') else
if R <> 0 then ShowMessage ('Выбрана сфера') else
if G <> 0 then ShowMessage ('Выбран объект зеленого цвета')
else
ShowMessage ('Ничего не выбрано');
Factive := True;
end;
Первый аргумент метода GetBackBuffer указывает номер присоединенного буфера, основан на нуле. Вторым аргументом является константа. В момент написания книги здесь можно использовать единственно возможное значение, D3DBACKBUFFER_TYPE_MONO. Последний аргумент метода - переменная типа Direct3DSurface8, в которую помещается результат. Поверхности в Direct3D очень похожи на знакомые нам по DirectDraw, на время доступа к их содержимому они должны запираться.
При анализе содержимого пиксела я предусмотрел поддержку только двух, наиболее распространенных, форматов пиксела, и этот код, возможно, вам придется дополнить.
Зеленую составляющую пиксела мы в этом примере никак не используем, но я оставил рассмотрение ее значения для предотвращения замечаний компилятора. Удалять этот код я не стал, вам он может понадобиться для выбора из трех объектов.
Выбор по цвету, разобранный в данном примере, вы можете использовать для идентификации сотен объектов. Ведь объекты могут различаться оттенками, и совсем не обязательно, чтобы они окрашивались именно в чистые цвета: вы можете использовать смеси всех трех цветов.
Туман
Простейшим средством передачи глубины пространства является включение дымки. Объекты сцены в таком режиме при удалении от наблюдателя становятся менее различимыми, погружаются в туман.
Работа с туманом в DirectBD очень простая. Достаточно включить указанный режим и задать несколько параметров. При воспроизведении графическая система будет учитывать эти установки, и никаких изменений в коде воспроизведения объектов сцены не требуется.
Параметры тумана таковы:
* формула, задающая закон эффекта (линейный или экспоненциальный); плотность дымки, указываемая для нелинейных законов; интервал, на протяжении которого эффект действует, используется для линейного закона; цвет тумана.
При линейном законе плотность дымки равномерно увеличивается по мере удаления от глаза наблюдателя. Дымка действует в пределах интервала от передней до задней плоскостей отсечения. Этот интервал можно сузить, задавая значение параметров D3DRS__FOGSТАRТ и D3DRS_FOGEND. Есть две схемы расчета тумана: пикселная и вершинная. Если задана первая схема, значения связанных с расстоянием параметров лежат в пределах от нуля до единицы и задают расстояния относительно текущих видовых параметров. Минимальное значение соответствует расстоянию до передней плоскости отсечения, максимальное соотносится с задней плоскостью. Во второй, вершинной схеме тумана значения параметров указывают на действительное расстояние в мировом пространстве. Для большей определенности я буду применять только одну, первую схему. Ей соответствует режим D3DRS_FOGTABLEKODE. Для использования вершинной схемы необходимо менять установки состояния D3DRS_FOGVERTEXMODE. В обеих схемах объекты, располагающиеся дальше границы действия тумана, становятся совершенно неразличимыми.
Нелинейных законов два: оба опираются на экспоненциальную зависимость, но в одном из них используется экспонента квадрата. Аргументом экспоненты в обоих случаях является произведение расстояния и весового фактора, называемого плотностью. Этот параметр должен быть вещественным и не превышать 1.
Проект каталога Ех05 поможет вам глубже постичь все вышесказанное. Тестовая композиция воспроизводится на панели, рядом с которой располагаются элементы, позволяющие менять текущие параметры тумана .Для возможности динамической смены параметров их значения хранятся в переменных:
var
FogDensity : Single = 1.0; // Плотность
FogStart : Single =0.4; // Расстояние, с которого туман действует
FogEnd : Single =1.0; // Граничное расстояние действия тумана
FogColor : DWORD = $00FFFFFF; // Цвет тумана, первоначально - белый
FOGTABLEMODE : DWORD = D3DFOG_LINEAR; // Закон тумана
with FD3DDevice do begin
// Включаем режим использования дымки
SetRenderState(D3DRS_FOGENABLE, DWORD (True));
// Используем пикселную схему расчета тумана
SetRenderState(D3DRS_FOGTABLEMODE, FOGTABLEMODE);
// Устанавливаем текущие параметры тумана
SetRenderState(D3DRS_FOGCOLOR, FogColor);
SetRenderState(D3DRS_FOGDENSITY, PDWORD (@FogDensity)л);
SetRenderState(D3DRS_FOGSTART, PDWORD (@FogStart)л);
SetRenderState(D3DRS_FOGEND, PDWORD (@FogEnd)");
end;
При изменении пользователем состояний интерфейсных элементов меняются значения соответствующих переменных:
procedure TfrmD3D.tbStartChange(Sender: TObject); // Ползунок "Fog Start''
begin
FogStart := tbStart.Position / 10;
end;
procedure TfrmD3D.tbEndChange{Sender: TObject); // Ползунок "Fog End"
begin
FogEnd := tbEnd.Position / 10;

