Как программировать на directx

Обновлено: 07.07.2024


-->Приветствую Вас Гость | RSS

Уроки по работе с DirectX, включая Direct3D и другие инструменты

Теперь создадим исходный файл:


  • В окне Solution Explorer, кликаем правой кнопкой на папке Source Files
  • Выбираем Add->New item
  • В открывшемся окне выбираем C++ File и вводим имя(например main.cpp)

Новый исходный файл откроется для редактирования.
Допишем в начало кода такие строки:

Для работы с DirectX в настройках проекта нужно указать пути к файлам и подключить библиотеки.(Для разработки на директе нужен DirectX SDK).
Для этого:

int WinMain(HINSTANCE hInstance,HINSTANCE hPrevinst, LPSTR cmdline,int showcmd)
<
//Код программы
return 0;
>

Теперь нужно создать главное окно приложения, в которое будем производить визуализацию. Напишем это функцией.
Для начала - объявим глобальные переменные:


HWND mWnd; //Дескриптор окна
IDirect3DDevice9* dev; //устройство Direct3D


LRESULT WINAPI WndProc(HWND Wnd, UINT msg, WPARAM wParam, LPARAM lParam)
<
switch(msg)
<
case WM_DESTROY:
<
if(Wnd==mWnd)
ExitProcess(0);
>break;
default: return DefWindowProc(Wnd,msg,wParam,lParam);
>
>

А большего нам и не нужно Итак, теперь нужно инициализировать Direct3D устройство.
Для этого напишем такую функцию:

bool CreateDirect3DDevice(int Width, int Height)
<
IDirect3D9* dir; //этот интерфейс нужен для создания устройства
dir=Direct3DCreate9(D3D_SDK_VERSION); //создание интерфейса Direct3D9.
D3DPRESENT_PARAMETERS param; //параметры устройства
ZeroMemory(&param,sizeof(param)); //очищяем
param.AutoDepthStencilFormat=D3DFMT_D16; //формат буфера глюбины - 16 бит
param.EnableAutoDepthStencil=true;//включение буфера глубины/стенсильного буфера
param.Windowed=true;//оконный режим
param.SwapEffect=D3DSWAPEFFECT_DISCARD;//не помню, но так надо
param.BackBufferFormat=D3DFMT_UNKNOWN;//формат back-буффера
if(!CreateRenderWindow(800,600)) return false;
return !FAILED(dir->CreateDevice(0,D3DDEVTYPE_HAL,mWnd,D3DCREATE_HARDWARE_VERTEXPROCESSING,&param,&dev)); //создание устройства с заданными параметрами
>

Если не понятны назначения и параметры функций - кури справку. Теперь программируем в основном коде программы.
В начале вызываем Функцию создания окна и устройства:

if(!CreateDirect3DDevice(800,600)) return -1;

Теперь создадим чё-нить, что будем отображать. В DirectX есть такая полезная вещь, как Mesh. Она позволяет удобно рисовать объекты
Также можно создавать примитивы. Создадим чайник. Для этого есть функция D3DXCreateTeapot()


ID3DXMesh *te;
D3DXCreateTeapot(dev,&te,0);//создаём чайник

Дальше устанавливаем стандартные настройки(материал, проэкция и свет)


D3DMATRIX pr;
D3DXMatrixPerspectiveFovLH((D3DXMATRIX*)&pr,3.1415/4,800.0f/600.0f,0.1,100); //считаем матрицу проэкции
dev->SetTransform(D3DTS_PROJECTION,&pr);//устанавливаем матрицу проэкции

dev->SetRenderState(D3DRS_ZENABLE,true); //Включаем Z-буффер, для управлений глубиной прорисовки объектов.

D3DMATERIAL9 mat; //создаём материал
ZeroMemory(&mat,sizeof(mat));
mat.Diffuse.a=1;
mat.Diffuse.r=1; //красный
dev->SetMaterial(&mat); //устанавливаем тукущий материал
D3DLIGHT9 l; //создаём свет
ZeroMemory(&l,sizeof(l));
l.Type=D3DLIGHT_POINT;//точечное освещение
l.Diffuse.a=1;
l.Diffuse.r=1;
l.Diffuse.g=1;
l.Diffuse.b=1; //белый цвет
l.Position=D3DXVECTOR3(2,5,-3); //позиция источника цвета
l.Range=100; //диапазон
l.Attenuation0=1; //.
dev->SetLight(0,&l);//установка света
dev->LightEnable(0,true);//включаем свет

dev->SetRenderState(D3DRS_LIGHTING,true);//включаем возможность освещения


Устанавливаем матрицу вида:


D3DMATRIX view;

D3DXMatrixIdentity((D3DXMATRIX*)&view); //устанавливаем матрицу вида, т.к. камера у нас не двигается - ставим пустую матрицу.
dev->SetTransform(D3DTS_VIEW,&view); //ставим

Всё, дальше лень комментировать, вобщем вот главный цикл. Что не понятно - спрашивай.

D3DMATRIX w;
D3DXMatrixTranslation((D3DXMATRIX*)&w,0,0,5);//матрица мира. Ставим объек в позицию 0, 0, 5
D3DMATRIX rm;
r+=0.01;
D3DXMatrixRotationY((D3DXMATRIX*)&rm,r);//матрица поворота
dev->SetTransform(D3DTS_WORLD,&w);//поворачиваем вокруг Y на r радиан


На Хабре уже есть много статей про использование вычислительных шейдеров с Unity, однако статью о использовании вычислительного шейдера на "чистом" Win32 API + DirectX 11 найти затруднительно. Однако эта задача ненамного сложнее, подробнее — под катом.

Для этого будем использовать:

  • Windows 10
  • Visual Studio 2017 Community Edition с модулем "Разработка классических приложений на C++"
    После создания проекта укажем компоновщику использовать библиотеку `d3d11.lib`.

Для подсчета количества кадров в секунду будем использовать стандартную библиотеку

Выводить количество кадров в секунду будем через заголовок окна, для чего нам понадобится формировать соответствующую строку

Не будем подробно рассматривать обработку ошибок, в нашем случае достаточно, чтобы приложение упало в отладочной версии и указало на момент падения:

Заголовочные файлы для WinAPI:

Заголовочные файлы для Direct3D 11:

Идентификаторы ресурсов для загрузки шейдера. Можно вместо этого загружать в память объектный файл шейдера, генерируемый компилятором HLSL. Создание файла ресурсов описано позже.

Константы, общие для шейдера и вызывающей части, объявим в отдельном заголовочном файле.

Объявим функцию обработки Windows-событий, которая будет определена позже:

Напишем функции для создания и уничтожения окна

Далее — инициализация интерфейса обращения к видеокарте (Device и DeviceContext) и цепочки буферов вывода (SwapChain):

Инициализация доступа из шейдеров к буферу, в который будет производиться отрисовка:

До инициализации шейдеров нужно их создать. Visual Studio умеет распознавать расширение файла, поэтому мы можем просто создать исходник с расширением .hlsl , или же напрямую создавать шейдер через меню. Я выбрал первый способ, т.к. все равно через свойства придется задавать использование Shader Model 5.



Аналогично создаем вершинный и пиксельный шейдеры.

В вершинном шейдере будем просто преобразовывать координаты из двумерного вектора (т.к. позиции точек у нас именно двухмерные) в четырехмерный (принимаемый видеокартой):

В пиксельном шейдере будем возвращать белый цвет:

Теперь вычислительный шейдер. Зададим такую формулу для взаимодействий точек:

При массе, принятой 1

Так будет выглядеть реализация этого на HLSL:

Можно заметить, что в шейдер включается файл SharedConst.h . Это тот заголовочный файл с константами, который включается в main.cpp . Вот содержание этого файла:

Просто объявление количества частиц и количества потоков в одной группе. Мы выделим по одному потоку каждой частице, поэтому количество групп зададим как PARTICLE_COUNT / NUMTHREADS . Это число должно быть целым, поэтому нужно, чтобы число частиц делилось на число потоков в группе.

Загрузку скомпилированного байткода шейдеров будем производить при помощи механизма ресурсов Windows. Для этого создадим следующие файлы:

resource.h , где будут содержаться ID соответствующего ресурса:

И resource.rc , файл для генерации соответствующего ресурса следующего содержания:

Где ShaderObject — тип ресурса, а compute.cso , vertex.cso и pixel.cso — соответствующие названия файлов Compiled Shader Object в выходной директории.

Чтобы файлы были найдены, следует в свойствах resource.rc прописать путь до выходной директории проекта:


Visual Studio автоматически распознала файл как описание ресурсов и добавила его в сборку, вручную это делать не нужно

Теперь можно написать код инициализации шейдеров:

Код инициализации буферов:

И код инициализации доступа к буферам из вычислительного шейдера:

Далее стоит указать драйверу использовать созданные шейдеры и связки с буферами:

Для подсчета среднего времени кадра будем использовать следующий код:

А на каждом кадре — вызывать такую функцию:

На случай, если размер окна изменился, нам нужно также изменить размер буферов отрисовки:

Инициа́ция (лат. initiatio — совершение таинства, посвящение) — обряд, знаменующий переход на новую ступень развития в рамках какой-либо социальной группы или мистического общества.
Википедия

Как понятно из написанного выше, сейчас я буду приобщать вас к некому таинству, переводить на следующую ступень знаний. Этим таинством будет программирование трехмерной графики и создание собственных игр. Курс будет состоять из нескольких лекций, знакомящих с основами DirectX, необходимыми для создания игр. Постепенно изучая DirectX, на протяжении всего курса мы и будем делать простую игру.

Большинство современных игр написано на зыке программирования С++ в связке с DirectX API. DirectX это разработанный компанией Микрософт интерфейс прикладного программирования (API - Application Programming Interface), который содержит в себе все структуры, константы, функции и объекты, необходимые для программирования игр вообще и трехмерной графики в частности. Ранее, до того, как Микрософт додумалась это сделать, каждому программисту приходилось писать все самостоятельно. Представляете, какой это адский труд. Хотя вряд ли представляете. Ну, можете просто поверить мне на слово.
Первая версия DirectX появилась в далеком 1995 году. На данный момент уже доступна одиннадцатая. Но поскольку официально ни 10 ни 11 версии не работают в Windows ХР, являющейся на данный момент самой распространенной операционной системой из семейства Windows, использовать мы будем DirectX 9. Все новые версии имеют полную совместимость с предыдущими, так что не переживайте на счет того, что мы взяли старую.
Еще стоит упомянуть, что для работы технология DirectX 9 должна поддерживаться видеокартой, но на данный момент это уже неактуально, поскольку вам вряд ли сейчас удастся найти видеокарту, которая его не поддерживает.

DirectX состоит из нескольких компонентов, каждый из которых служит для своих целей.

1. DirectX Graphics – набор интерфейсов для работы с трехмерной графикой.
2. DirectInput: - предназначен для обработки данных, поступающих с устройств ввода – мыши клавиатуры, иных манипуляторов.
3. DirectPlay: - интерфейс поддержки сети.
4. DirectSound: - интерфейс для работы со звуком. Ранее в составе DirectX находился еще один звуковой интерфейс – DirectMusic, но с 2008 года он был исключен. По слухам та же участь ждет и DirectSound.
5. DirectShow: - интерфейс, используемый для ввода/вывода видео и аудиоданных.

На этом знакомство закончим и перейдем к более насущным темам.






А для звука можно использовать Adobe Audition или Sound Forge.



Кроме перечисленных можно взять любые другие, просто с этими я работал и в случае чего могу что-то подсказать. В лекциях описывать методы работы с этими программами я не буду, только в крайнем случае. Если вам это нужно, воспользуйтесь дополнительной литературой.
Ну и на последок. На компьютере, на котором предполагается запуск ваших игр, должен быть установлен DirectX runtime. Это пакет библиотек, необходимых для функционирования DirectX. В вашем случае он установится вместе с SDK. Ну а другим пользователям придется скачать его с интернета, это если он у них еще не установлен, поскольку поставляется с большинством современных игр.
Не думаю, что у вас возникнут какие-то проблемы с установкой всего необходимого ПО, но один момент все же объясню. Установка DirectX SDK должна производится после установки Microsof Visual Studio, чтобы в настройках среды прописались необходимые пути к заголовочным файлам и библиотекам. Если этого по каким-то причинам не произошло(например вам не по трафику скачать полное SDK и вы смогли достать только нужные файлы), то эту работу придется проделать вручную.
Делается это так:
Открываем Microsof Visual Studio и кликаем на пункте меню Сервис→Параметры и видим вот такое окно Параметры:


Затем объявляем три переменные:
Первая - это структура, содержащая различные параметры окна(Они описаны в комментариях в исходном коде.)

Урок DirectX 12. Рисуем первый треугольник

DirectX 12 — это последняя версия собственного API компьютерной графики от Microsoft, используемого для платформ Windows и Xbox. Он, как и Vulkan, нацелен на создание менее сложного драйвера и API, более близкого к архитектуре современных графических процессоров.

DirectX фокусируется на рендеринге в реальном времени, поэтому он предназначен для разработчиков игр и систем автоматизированного проектирования (CAD). Поскольку это отраслевой стандарт API компьютерной графики, можно ожидать, что почти все совместимые аппаратные средства будут иметь его надежную поддержку, и он станет стандартом для коммерческих проектов.

Этот графический API является самым популярным и вездесущим из всех: от программ для создания 3D/изображений наподобие Marmoset Toolbag 3, Adobe PhotoShop, Autodesk Maya, до коммерческих игр вроде OverWatch от Blizzard и Fortnite от Epic, подавляющего большинства игр на Steam от Valve и многого другого (несмотря на эксклюзивность платформы).

DirectX 12 сейчас поддерживается в:

  • Windows 10
  • Xbox One
  • Xbox One X

В Windows 7 имеется частичная поддержка через D3D12 On 7.

Его поддерживает множество языков:

Я подготовил хранилище Github со всем, что понадобится. На современном C++ мы собираемся пройтись по приложению Первый Треугольник. Это программа, которая создает треугольник и визуализирует его на экране.

Подготовка

Теперь напечатайте в терминале следующее.

git submodule update --init

Обзор

Документация DirectX 12 рекомендует использовать ComPtr <T> в качестве альтернативы к std :: shared_ptr <T>, потому что так лучше отлаживать и легче инициализировать структуры данных DirectX 12.

Независимо от того, выберете ли вы ComPtr <T> или нет, этапы рендеринга растровой графики с помощью DirectX 12 очень похожи на этапы других современных графических API:

  1. Инициализация API — создаются ваши Фабрика, Адаптер, Устройство, Очередь, Распределитель команд, Список команд, Цепочка обмена.
  2. Инициализация ресурсов — ваш Буфер вершин, Индексный буфер, Однородный буфер, Представления целей визуализации, Графический конвейер, Примитивы синхронизации.
  3. Визуализация — обновление ваших однородных данных, добавление команд в очередь и ожидание следующего фрейма.

Далее будут объяснены фрагменты, которые можно найти в хранилище Github, с определенными опущенными частями и переменными-членами (mMemberVariable), объявленными встроенными без префикса m, чтобы их тип был легче видеть. Примеры здесь могут работать сами по себе.

Создание окна

Мы используем CrossWindow для создания кроссплатформенного окна, поэтому создать окно и обновить его очень просто:

Читайте также: