Привіт, дорогі мої детишечки 8-)
У попередньому уроці ми розглянули, як працювати з текстурами в Direct3D. Сьогодні ж ми розглянемо таку можливість, як мультитекстурирование. Що ж це таке? Мультитекстурирование - це накладення декількох текстур на один полігон. Найчастіше такий метод застосовується для імітації освітлення. Тобто, заздалегідь розраховується ступінь освітленості тієї чи іншої частини полігональної моделі, а потім складається карта освітленості (light map), яка накладається "поверх" основний текстури об'єкта, в результаті чого створюється ефект нерівномірного освітлення поверхні. Такий прийом набагато швидше, ніж розрахунок освітлення "на льоту", тому він знайшов широке застосування в іграх. Також існує безліч областей застосування мультитекстурирования, наприклад, для імітації деяких спецефектів. В даному уроці ми розглянемо імітацію освітлення полігону. Цей приклад заснований на попередньому уроці, так що для які не читали, рекомендую його прочитати: Direct3D: Текстурування.
Ну що ж, поїхали!
Для початку, я трохи змінив формат наших вершин, додавши туди параметр, що визначає їх колір. В принципі, ця дія не обов'язково, але воно надає широке поле для експериментів і дозволяє домогтися гарних ефектів. За допомогою нього ми зможемо змінити колір нашого "прожектора" (світла). Причому кінцевий колір виходить шляхом інтерполяції колірної складової кожної з вершин. За замовчуванням (якщо колір не заданий), використовується білий колір. Тепер наш формат вершин виглядає наступним чином:
Для другої текстури можна використовувати свої текстурні координати, для цього треба додати в опис вершин ще пару координат tu і tv, а також змінити прапор D3DFVF_TEX1 на D3DFVF_TEX2. Другий набір текстурних координат можна використовувати, наприклад, для анімації переміщення джерела світла. Для цього перший набір залишається колишнім, а другий набір змінюється. Природно, можна використовувати і більш 2 текстур. Direct3D допускає використання одночасно до 8 текстур.
Далі нам необхідно завантажити другу текстуру. Детально ця дія була описано раніше, так що не будемо загострювати на цьому свою увагу.
if (FAILED (D3DXCreateTextureFromFile (g_pd3dDevice, "Spotlight.bmp", g_pSpotLight)))
return false;
Для реалізації мульти-текстурування в Direct3D використовуються текстурні рівні (texture stages). Кожна з максимально восьми текстур може бути поміщена в один з цих рівнів. Робиться це за допомогою функції SetTexture наступним чином:
Тобто, в перший рівень ми встановлюємо вихідну текстуру, а в другій ту, що будемо накладати зверху. Перший параметр цієї функції як раз і вказує номер рівня, в який необхідно помістити текстуру.
Далі ми повинні встановити текстурні стану. За допомогою них можна домогтися безлічі різних ефектів. Я використовував практично настройки за замовчуванням, але завжди можна поекспериментувати. Далі, я опишу деякі можливі стани.
У першому рядку ми встановлюємо той набір текстурних координат, який ми хочемо використовувати для відповідної текстури (текстура визначається за номером рівня - перший параметр функції). У нашому прикладі ми використовуємо один набір координат, тому встановлюємо D3DTSS_TEXCOORDINDEX в 0. У другому рядку ми встановлюємо режим фільтрації текстур. Я встановив білінійну фільтрацію.
Те ж саме робимо для другої текстури:
Розглянемо залишилися текстурні стану:
D3DTSS_COLORARG1 (2) - це стан визначає перший (другий) колірної аргумент для текстурного рівня, може приймати наступні значення:
- D3DTA_CURRENT - аргумент текстури - стан, з яким відображався попередній текстурний рівень. Якщо це перший текстурний рівень (0), то цей аргумент рівносильний D3DTA_DIFFUSE.
- D3DTA_DIFFUSE - аргумент текстури - колір, отриманий інтерполяцією кольору вершин з використанням затінення по Гуро. Якщо вершини не містять колірної складової, то вибирається білий (0xffffff) колір.
- D3DTA_TEXTURE - аргумент текстури - колір текстури для даного текстурного рівня.
D3DTSS_ALPHAARG1 (2) - визначає перший (другий) альфа аргумент для текстурного рівня може приймати ті ж значення, що і D3DTSS_COLORARG1 (2). Значення за замовчуванням - D3DTA_TEXTURE. Якщо для даного рівня текстура не встановлена, то використовується D3DTA_DIFFUSE.
D3DTSS_COLOROP - 'це стан встановлює яким чином буде змішуватися кольору текстур. Може приймати наступні значення:
- D3DTOP_DISABLE - відключає висновок текстур з поточного рівня (stage) і для всіх вищих рівнів. Щоб відключити висновок текстур встановіть це значення для першого текстурного рівня.
- D3DTOP_SELECTARG1 (2) - для виведення буде використовуватися перший (другий) колірної або альфа аргумент.
- D3DTOP_MODULATE - перемножує колірні компоненти з ARG1 і ARG2
- D3DTOP_MODULATE2X (4Х) - перемножує колірні компоненти і зрушує результат на 1 (2) біт вліво, в результаті чого виходить множення результату на 2 (4), тобто зображення стає яскравішим.
- D3DTOP_ADD - складає колірні компоненти ARG1 і ARG2
- D3DTOP_SUBTRACT - результуючий колір виходить шляхом вирахування другого аргументу ARG2 з першого ARG1.
За замовчуванням D3DTSS_COLOROP для першого текстурного рівня має значення D3DTOP_MODULATE, а для всіх інших D3DTOP_DISABLE.
Крім перерахованих існує ще кілька станів, про них можна прочитати в DirectX8 SDK Help розділ D3DTEXTURESTAGESTATETYPE
Після всіх цих операцій залишається тільки намалювати наш примітив. Робиться це стандартним чином:
Якщо все зроблено правильно, то ми повинні отримати нібито освітлений прожектором полігон. Ось що вийшло у мене: