Всех горячо приветствую! Темы, как я говорил, пошли несложные, да и у меня достаточно энергии, так что держите новую тему.
В двух словах о том, что такое Command Lists. Раньше все графические команды выполнялись по завершении рисования (EndDraw), но может быть такая ситуация: есть функция, в ней рендер мира, но всё в одной функции — довольно так себе. Вы же можете, например, отрисовывать разные локации, и многие сразу задумаются о том, чтобы использовать разные функции — что совершенно правильно. Но было бы неплохо создать массив команд, чтобы вместо функций просто оперировать массивом, а также такой массив не привязан к разрешению.
Кроме этого, захотелось бы нам ещё применить к нему эффекты из прошлой статьи или создать узор. И, кроме всего этого, нам бы ещё сделать оптимизацию. Вот до массива мы использовали 50 команд снова и снова, тратили ресурсы CPU на расчёт, а поместили в массив — один раз потратили ресурсы, и теперь просто и легко отправляем всё в GPU.
И этот инструмент уже существует, отвечая на все вышеописанные запросы и называется Command List, ну или лист команд. Поддерживается с Windows 8.
Это очень интересный инструмент, при грамотном подходе позволяющий снизить нагрузку на CPU, но не на GPU.
Прежде чем перейти к примерам, важно сказать, что Command List наследуется от ID2D1Image со всеми вытекающими: он может быть входом для эффекта, источником для ID2D1ImageBrush и аргументом для DrawImage.
Также важно, что Command List не хранит копию ресурсов, а лишь ссылки на них. А отсюда вытекает следующее:
-
Ресурсы должны существовать в момент воспроизведения Command List. Если вы удалите битмап до воспроизведения — будет ошибка.
-
Изменение ресурса после записи отразится на воспроизведении.
-
Command List сам по себе занимает мало памяти — он хранит только инструкции и ссылки, а не сами данные.
-
Все ресурсы создаются и уничтожаются вне Command List.
Собственно, пример создания (разумеется, через DeviceContext):
ComPtr<ID2D1CommandList> pCommandList;HRESULT hr = pDeviceContext->CreateCommandList(&pCommandList);if (FAILED(hr)) { // Обработка ошибки}
Собственно, ничего сложного. Теперь — как записать команды (набросок кода):
// Устанавливаем Command List как цельpDeviceContext->SetTarget(pCommandList.Get());// Начинаем рисование - все команды будут записаны в Command ListpDeviceContext->BeginDraw();// ... здесь ваши команды рисования ...pDeviceContext->DrawRectangle(...);pDeviceContext->FillGeometry(...);pDeviceContext->DrawText(...);pDeviceContext->EndDraw();
Ну и потом не забудьте восстановить цель рендера.
ВАЖНО! Без закрытия Command List нельзя использовать:
pCommandList->Close();
Разумеется, после закрытия добавлять команды уже нельзя. Теперь, чтобы воспроизвести содержимое Command List, достаточно написать:
pDeviceContext->BeginDraw();// Рисуем Command List в указанной позицииpDeviceContext->DrawImage(pCommandList.Get());// Или со смещениемD2D1_POINT_2F offset = D2D1::Point2F(100.0f, 50.0f);pDeviceContext->DrawImage(pCommandList.Get(), offset);pDeviceContext->EndDraw();
Пример создания кисти-узора на основе Command List:
// 1. Создаём Command List с узоромComPtr<ID2D1CommandList> pPatternList;pDC->CreateCommandList(&pPatternList);ComPtr<ID2D1Image> pOldTarget;pDC->GetTarget(&pOldTarget);pDC->SetTarget(pPatternList.Get());pDC->BeginDraw();// Рисуем элемент узора (например, ромб)DrawMyPatternElement(pDC);pDC->EndDraw();pPatternList->Close();pDC->SetTarget(pOldTarget.Get());// 2. Создаём Image Brush из Command ListD2D1_IMAGE_BRUSH_PROPERTIES imageBrushProps = D2D1::ImageBrushProperties( D2D1::RectF(0, 0, 50, 50) // область узора);D2D1_BRUSH_PROPERTIES brushProps = D2D1::BrushProperties(1.0f);ComPtr<ID2D1ImageBrush> pPatternBrush;pDC->CreateImageBrush( pPatternList.Get(), imageBrushProps, brushProps, &pPatternBrush);// 3. Используем кисть для заливкиpDC->BeginDraw();pDC->FillEllipse(D2D1::Ellipse(D2D1::Point2F(400, 300), 150, 100), pPatternBrush.Get());pDC->EndDraw();
Так как всё это мы уже проходили, особо пояснять нечего. Тема, как видите, несложная, отсюда и короткая, но важная. А лепить что-то ещё я решил, что не стоит.
Вообще, если поискать в интернете, прям подробных книг по Direct2D я не нашёл. А у нас тут вполне подробно и кратко, и каждая статья — на определённую тему. Можно даже сказать — экспресс-курс.
Всем спокойной ночи или удачного дня, и удачи!
При желании материально поддержать перевод и структурирование информации — средства можете отправить через сбор в ЮМани.
ссылка на оригинал статьи https://habr.com/ru/articles/1053608/