Основная проблема возникает, когда WPF создает эффект для дерева с частичным смещением пикселей. Есть два основных подхода, которые мы могли бы сделать для аппаратного пути:
1) Создайте промежуточную текстуру, соответствующую пикселям экрана, и визуализируйте дерево с частичным смещением в пределах этой текстуры. Затем при переносе этого промежуточного элемента обратно на экран мы можем использовать выровненные по пикселям квадраты и использовать простую выборку ближайших соседей, поскольку содержимое выровнено по пикселям.
2) Создайте промежуточную текстуру, которая соответствует границам дерева, и визуализируйте дерево с нулевым смещением в пределах этой текстуры. Затем при переносе промежуточного изображения обратно на экран нам нужно использовать квад, который покрывает частичные пиксели. Поскольку квад может покрывать частичные пиксели, важен режим выборки. Режимы выборки, такие как NearestNeighbor, могут вызывать артефакты сглаживания, которые могут зависеть от графического процессора.
WPF выбрал # 2 и принудительную выборку ближайшего соседа - если только дерево, у которого было какое-либо преобразование, кроме смещения или масштаба (чаще всего вращения), в этом случае не принудительно использовало билинейную выборку. Это несколько отличается от пути растеризации программного обеспечения, который будет использовать режим интерполяции, действующий для дерева, если только дерево не имеет преобразования, отличного от смещения или масштаба, и в этом случае оно также принудительно вызывает билинейную выборку.
Мы «исправляем» эту проблему, приводя аппаратный путь в соответствие с программным путем. Это означает, что мы будем уважать действующий режим выборки для визуализируемого дерева. Это можно установить из управляемого кода с помощью вложенного свойства RenderOptions.BitmapScalingMode. Значением по умолчанию является Линейный, что является более подходящим режимом выборки, когда квадратор покрывает частичные пиксели. Тем не менее, он вносит заметную размытость - но так же, как и растеризация программного обеспечения.
Для 4.0 есть несколько обходных путей:
1) Не допускайте расположения дерева элементов на частичном пикселе. Например, вы можете установить для свойства UseLayoutRounding значение true для контейнеров, которые позиционируют элемент с эффектом.
2) Примените небольшое вращение, чтобы заставить путь рендеринга использовать билинейную интерполяцию. Это может быть очень мало, например, RenderTransform с <RotateTransform Angle="0.00000000001"/>
Обратите внимание, что пользовательские эффекты ShaderEffects используют явные сэмплеры с настраиваемыми режимами сэмплирования.
Клиенты смогут узнать текущее поведение, установив для присоединенного свойства RenderOptions.BitmapScalingMode значение "NearestNeighbor". Обратите внимание, что даже это будет игнорироваться, если дерево вращается, и вместо этого будет использоваться билинейная выборка. Остается верным, что на некоторых графических процессорах такие эффекты, как DropShadow, могут сталкиваться с артефактами сглаживания при использовании выборки NearestNeighbor.
Также обратите внимание, что при применении эффекта к изображению одно и то же значение присоединенного свойства RenderOptions.BitmapScalingMode будет использоваться как для содержимого изображения, так и для промежуточной текстуры эффекта. Если вам нужно изображение с выборкой NearestNeighbor, но с эффектом, использующим линейную выборку, вам потребуется применить эффект к контейнеру изображения, такому как простой холст, содержащий изображение.