Глава 1 - пристрій direct3d

пристрій Direct3D

Є три конструктора, які можна використовувати для створення пристрою. Зараз ми використовуємо один з них, а з іншими познайомимося в наступних розділах. Той, на якому ми зосередимо увагу, отримує такі аргументи:

Що ж означають всі ці параметри, і як їх використовувати? Ну що ж, перший аргумент, adapter. указиваает-яка фізична пристрій буде представляти даний екземпляр класу. У кожного пристрою в вашому комп'ютері є унікальний ідентифікатор (зазвичай вони знаходяться в діапазоні від 0 до числа, на одиницю меншого, ніж кількість наявних пристроїв). Значення 0 відповідає пристрою, яке використовується за умовчанням.

Перевантажені КОНСТРУКТОРИ ПРИСТРОЇВ
Другий перевантажений конструктор пристрою ідентичний першому за винятком параметра renderWindow. який отримує значення типу IntPtr для некерованого (який не належить до Windows Forms) вікна. Останній перевантажений конструктор отримує єдине значення типу IntPtr. є некерованим COM-покажчиком на інтерфейс IDirect3DDevice9. Вони можуть використовуватися, якщо вам необхідно працювати з некерованими додатками з вашого керованого коду.

ПРОГРАМНА емуляції ПРИСТРОЇВ
Зверніть увагу, що допоміжний растеризатор поставляється тільки з DirectX SDK, а бібліотеки часу виконання DirectX не пропонують цієї можливості. Останнє значення, DeviceType.Software. означає, що ви використовуєте власний програмний растеризатор. Якщо ви не знаєте про те, чи є у вас програмний растеризатор, ігноруйте цей варіант.

Аргумент renderWindow прив'язує вікно Цей пристрій. Оскільки класи елементів управління Windows Forms містять дескриптор вікна, досить просто використовувати успадковані клас як нашого вікна візуалізації. У цьому параметрі ви можете вказати форму, панель або будь-який інший клас, успадкований від елемента управління. Зараз ми будемо використовувати форми.

Останній параметр конструктора, presentationParameters. управляє тим, як пристрій відображає дані на екрані. Через цей клас можна керувати будь-якими параметрами відображення пристрою. Пізніше ми більш детально поговоримо про цю структуру, а зараз приділимо вінманіе тільки членам Windowed і SwapEffect.

Член Windowed є логічною змінною, що визначає чи працює пристрій в повноекранному режимі (false) або у віконному режимі (true).

Тепер, володіючи цією інформацією, ми можемо створити пристрій. Давайте повернемося до коду і зробимо це. Спершу нам буде потрібно об'єкт пристрою, який ми будемо використовувати в нашому додатку. Ми додамо новий закритий член device. Вставте наступний рядок в визначення класу:

Тепер додамо до нашого класу нову функцію з ім'ям InitializeGraphics. де ми зможемо використовувати конструктор, який щойно обговорили. Додайте до вашого класу наступний код:

Як бачите, ми створюємо аргумент з параметрами показу, встановлюємо згадані вище члени (Windowed і SwapEffect), а потім створюємо пристрій. В якості ідентифікатора адаптера ми вказуємо 0, що означає яка буде використовуватися під адаптер. Ми створюємо апаратний пристрій, а не допоміжний або програмний растеризатор. Зверніть увагу на використання ключового слова this як вікна візуалізації. Оскільки наш додаток і, зокрема, даний клас, є формою Windows, ми просто використовуємо її. Крім того, як згадувалося раніше, ми покладаємо обробку вершин на центральний процесор. Все чудово, але зараз цей код ніколи не викликається, так що давайте змінимо функцію Main нашого класу, щоб вона зверталася до цього методу. Внесіть в створений за замовчуванням статичний метод Main наступні зміни:

У функції ми зробили кілька змін. По-перше, ми додали інструкцію using до оператора створення форми. Це гарантує, що наша форма буде доступна, коли додаток покине зону видимості даного блоку. Потім ми додали команду Show для форми. Зробивши це ми гарантуємо, що вікно буде дійсно завантажено і відображено (і, отже, буде створений дескриптор вікна) до того, як ми спробуємо створити пристрій. Потім ми викликаємо нашу функцію, що виконує створення пристрою, і використовуємо стандартний метод Run для запуску програми. Скомпілюйте додаток і запустіть його. Вітаю, ви тільки що успішно створили свою першу Direct3D-додаток.

Гаразд, слід визнати, що додаток виключно нудне. Воно створює пристрій, але нічого не робить з ним, так що подивившись на запущене застосування ви не помітите жодних відмінностей від створеного на самому початку «порожнього» проекту C #. Давайте змінимо це, і що-небудь визуализируем на екрані.

У класів форм є вбудована можливість визначити момент, коли їм треба перемалювати себе: використання перевизначеного методу OnPaint (або перехоплення події Paint). Дана подія відбувається кожного разу, коли вікно необхідно перемалювати. Схоже, це прекрасне місце для розміщення нашого коду візуалізації. Ми зараз не будемо робити що-небудь вражає уяву, а просто очистимо вікно, заливши його заданим кольором. Додайте до визначення вашого класу наступний код:

Для суцільної заливки вікна заданим кольором ми використовуємо метод пристрою Clear. Зараз ми використовуємо один із зумовлених квітів з ім'ям CornflowerBlue (волошковий). Перший параметр методу вказує, що саме ми хочемо очистити; в даному прикладі ми очищаємо цільове вікно. З іншими членами перерахування ClearFlags ми познайомимося пізніше. Другий параметр - це використовуваний для очищення колір, а інші два параметра поки для нас не важливі. Після того, як пристрій очищено, нам необхідно оновити зображення на екрані монітора. Це робить метод Present. Існує кілька перевантажених версій цього методу; показана тут оновлює всю область пристрою. Решта перевантаження ми обговоримо пізніше.

Запустивши додаток тепер, ви помітите, що фон вікна стає волошковим. Ви можете змінювати розмір вікна або розгортати його на весь екран, і кожен раз, коли ви робите це, поверхня вікна заповнюється волошковим кольором. Зараз ми можемо бачити, як наш пристрій щось робить, але результат все ще досить нудний. Того ж результату можна домогтися задавши колір фону форми в середовищі розробки. Необхідно намалювати що-небудь більш вражаюче.

Основний об'єкт, мальованої в тривимірній графіці, це трикутник. Достатня кількість трикутників дозволяє представити все, що завгодно, в тому числі і плавні криві поверхні. Так що цілком природно, що нашим першим малюнком повинен бути окремий трикутник. Щоб спростити процес малювання цього трикутника, ми не будемо турбуватися про такі речі, як «світовий простір» або «перетворення» (з цими темами ви незабаром познайомитеся), а намалюємо трикутник, використовуючи екранні координати. Отже, щоб намалювати наш чудовий трикутник, необхідні дві речі. По-перше, нам потрібна якась структура даних, де буде зберігатися інформація про трикутнику. По-друге, треба повідомити пристрою, про те, що треба намалювати трикутник.

На щастя, в DirectX для керованого коду вже є конструкція для зберігання даних трикутників. Це клас CustomVertex в просторі імен Direct3D. поселив багато загальновживані конструкції формату вершин. використовувані в Direct3D. Структура формату вершин зберігає дані в форматі, який Direct3D розуміє і може використовувати. Пізніше ми більш детально обговоримо ці структури, а зараз для нашого трикутника виберемо структуру TransformedColored. Вона повідомляє Direct3D, що наш трикутник не треба перетворювати (тобто обертати або переміщати), оскільки ми вказуємо його місце розташування в екранних координатах. Також для кожної точки (вершини) трикутника включена колірна компонента. Повернемося до нашого перевизначення методу OnPaint. і додамо наступний код після виклику очищення пристрою:

Кожен член створеного масиву представляє одну точку нашого трикутника, так що необхідно три елементи. Потім для кожного члена масиву ми присвоюємо властивості Position структуру Vector4. Місцезнаходження перетвореної вершини включає координати X і Y в просторі екрану (щодо початку координат вікна), а також координату Z і значення rhw (зворотне або однорідне w). Останні два члена в даному прикладі ігноруються. Структура Vector4 дуже зручна для зберігання подібної інформації. Потім ми встановлюємо кольори кожної з вершин. Зверніть увагу, що при використанні стандартних кольорів необхідно викликати метод ToArgb. Direct3D очікує, що кольори будуть представлені у вигляді 32-розрядних цілих чисел, і даний метод перетворює наявний колір в цей формат.

Зауважте, що при визначенні координат трикутника використовуються поточні ширина і висота вікна. Це зроблено, щоб розміри трикутника змінювалися разом з вікном.

Тепер у нас є дані і треба повідомити Direct3D про те, що ми хочемо намалювати наш трикутник, і як треба його малювати. Це робиться шляхом додавання до перевантаженому методу OnPaint наступного коду:

Що, чорт візьми, все це означає? Не хвилюйтеся, все відносно просто. Метод BeginScene дозволяє Direct3D дізнатися, що ми збираємося щось малювати, і підготуватися до цього. Тепер, коли ми сказали Direct3D, що збираємося щось намалювати, нам треба повідомити що саме ми будемо малювати. Для цього призначена властивість VertexFormat. Воно повідомляє Direct3D, який формат фіксованого конвеєра функцій ми хочемо використовувати. У нашому випадку ми використовуємо конвеєр для перетворених і забарвлених вершин. Не турбуйтеся, якщо вам поки незрозумілі слова «фіксований конвеєр функцій», ми поговоримо про це пізніше.

У функції DrawUserPrimitives відбувається власне малювання. Так що означають її параметри? Перший параметр - це тип примітивів, які ми плануємо малювати. Доступно декілька різних типів, але зараз ми хочемо просто намалювати список трикутників, так що виберемо тип TriangleList. Другий параметр - це скільки трикутників ми збираємося малювати; для списку трикутників це число завжди має дорівнювати кількості вершин в масиві, ділення на три. Оскільки ми малюємо один трикутник, природно, тут вкажемо 1. Останній параметр функції - це дані, які Direct3D буде використовувати для малювання трикутника. Ми вже створили масив даних, так що залишилося вказати його тут. Останній метод, EndScene. просто повідомляє Direct3D, що ми не будемо більше малювати. Після кожного виклику BeginScene ви повинні викликати EndScene.

Тепер скомпілюйте і запустіть наше новий додаток. Зверніть увагу, що на кольоровому тлі з'явився розфарбований трикутник. Важливо відзначити, що кольори вершин трикутника - це ті кольори, які ми поставили в коді, але всередині трикутника кольору змішуються один з іншим. Direct3D автоматично интерполирует кольору на поверхні трикутника. Спробуйте змінити вибрані мною кольору і подивіться, який ефект це справить.

Ох, здається ми зламали наш додаток! Його запуск показує нам чорний екран, на якому іноді миготить наш трикутник. При зміні розмірів вікна цей ефект проявляється більш чітко. Це погано, але що сталося? Справа в тому, що Windows намагається бути розумною і перемальовує поточну форму (вона у нас пусто), після того, як вікно оголошено недійсним. Це перефарбування проходить повз нашого перевизначеного методу OnPaint. Виправити ситуацію досить просто, змінивши стиль створюваного вікна. У конструкторі вашої форми замініть скекцію TODO на наступний рядок:

Тепер при запуску програми все працює як очікувалося. Ми повідомили вікна, що вся перерисовка повинна відбуватися всередині перевизначеного методу OnPaint (WmPaint є звичайним повідомленням Win32) і наше вікно непрозоро. Це означає, що не буде ніякого малювання поза вікном, і все, що відбувається залежить від нас. Також можна відзначити, що якщо ви зміните розміри вікна так, що у нього не буде видимою клієнтської області, то буде згенеровано виняток. Якщо це дійсно турбує вас, можете змінити параметр, що визначає мінімальні розміри форми.