Всех горячо приветствую! Темы, как я говорил, пошли несложные, да и у меня достаточно энергии, так что держите новую тему.
В двух словах о том, что такое 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 List pDeviceContext->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 List D2D1_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 я не нашёл. А у нас тут вполне подробно и кратко, и каждая статья — на определённую тему. Можно даже сказать — экспресс-курс.
Всем спокойной ночи или удачного дня, и удачи!
При желании материально поддержать перевод и структурирование информации - средства можете отправить через сбор в ЮМани.