Предотвращение масштабирования изображения в области просмотра Direct3D (SlimDX) - PullRequest
1 голос
/ 06 июля 2011

У меня есть сцена Direct3D11, настроенная в SlimDX в окне.Рендеринг выполняется в отдельном потоке.

Есть ли способ предотвратить растягивание рендерера изображения, когда оно обращается к элементу управления с измененным размером?Я пробовал ModeDescription.Scaling = DisplayModeScaling.Centered, и это, похоже, не имеет никакого эффекта.Я что-то упускаю?

(я уже обновляю целевой размер рендеринга. Я спрашиваю это потому, что когда я изменяю размер элемента управления, он растягивает изображение, чтобы заполнить элемент управления за доли секунды доЦель рендеринга обновляется с новым размером. Это приводит к тому, что при изменении ее размера она мерцает ужасно. Если бы я мог сбросить цель рендеринга чуть быстрее, это могло бы избавить от мерцания. Хранение изображения в углу без его масштабированияотлично, так как в конечном итоге он вообще не будет масштабироваться.)

Обходной путь 1: Можно поместить цель рендеринга внутри элемента управления.Когда окно изменяет размеры, изменяйте размер только элемента управления, используя специальный метод, который сначала останавливает рендеринг, затем обновляет буферы и начинает рендеринг снова.Это немного взломать, хотя.Мне нужно дождаться завершения цикла рендеринга, затем заблокировать его, затем изменить его размер, затем разблокировать.

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

Обходной путь 3 : Вместо того, чтобы вообще изменять размеры элемента управления, можно сделать его максимально большимРазмер это может быть, но обрезается (внутри окна).Изменение размера не требуется, но прямоугольник ножниц должен поддерживаться аналогично обходным путям, описанным выше, если вы не возражаете против рендеринга большого количества пикселей вне экрана.Рендеринг двадцати или более дополнительных строк и столбцов пикселей имеет благоприятный эффект немедленного предоставления изображения на краю, когда размер окна уменьшается до большего.

В идеале изменение размера должно выполняться непосредственно из потока пользовательского интерфейса (не нужно дурачиться с его задержкой и повторным вводом потока пользовательского интерфейса из потока визуализации).Это не является обязанностью потока рендеринга, и это замедляет его.Аналогично, изменение размера буфера должно выполняться в потоке рендеринга для максимальной производительности (не нужно дурачиться с ожиданием / блокировкой / изменением размера / разблокировкой).Единственная причина, по которой это не работает, заключается в том, что поток рендеринга масштабируется, если изменение размера выполняется до изменения размера буферов.

Таким образом, мой вопрос остается в силе: Есть ли способ рендеринга без масштабирования?

Ответы [ 2 ]

1 голос
/ 06 июля 2011

Я собираюсь ответить на этот вопрос с точки зрения используемых API-интерфейсов Win32, которые могут потребовать некоторого изящества для перевода в управляемую среду .NET и SlimDX.

Когда вы перетаскиваете или изменяете размер окна, окна в основном перехватывают ваш почтовый насос и создают новый, специально разработанный для эффективной логики изменения размера. Эта операция более или менее модальна, пока не будет завершена. Многие сообщения, которые вы обычно получаете, буквально блокируются до тех пор, пока не будет выполнено изменение размера или перетаскивание. В терминах приложения вы получаете WM_ENTERSIZEMOVE, когда это поведение начинается, и либо WM_EXITSIZEMOVE, либо WM_CAPTURECHANGED, когда оно заканчивается. Вам необходимо проверить оба этих сообщения, так как при перетаскивании alt-tabing отправляется WM_CAPTURECHANGED, а не WM_EXITSIZEMOVE!

Все это означает, что когда вы получаете WM_ENTERSIZEMOVE, вы можете установить флаг и знать, что все сообщения WM_SIZE и WM_MOVE, которые появляются впоследствии, предназначены для операции перетаскивания. Как правило, изменение размеров целей рендеринга, отслеживание и отмена выделения всех ресурсов пула по умолчанию - очень медленная операция, которую стоит отложить до завершения перетаскивания / изменения размера. У этого есть побочный эффект растягивания окна, что является точно такой же проблемой, которую вы описываете здесь, и вы хотите это исправить.

Должна быть возможность добавить специальные обработчики в WM_SIZE, WM_MOVE или WM_SIZING и WM_MOVING, которые вызывают синхронный рендеринг и перерисовку через SendMessage (в отличие от PostMessage), когда они происходят, но вам нужно будет убедиться, что вы только делаете это когда внутри модального цикла принадлежит WM_ENTERSIZEMOVE.

0 голосов
/ 06 июля 2011

Я бы порекомендовал либо принудительно настроить окно к фиксированному размеру (что кажется довольно распространенным), либо не перерисовывать элемент управления D3D до тех пор, пока изменения не будут выполнены (или просто очистить его черным).

Кажется, есть способ сделать то, что вы хотите, поскольку я видел игры, способные изменять размер без мерцания, но я, к сожалению, понятия не имею, как это сделать. Блокировка размера окна и предоставление меню было старым решением.

...