Графы точности и числового отсечения в эффекте
Приложения, отрисовывющие эффекты с помощью Direct2D, должны обеспечить требуемый уровень качества и предсказуемости в отношении числовой точности. В этом разделе описываются рекомендации и соответствующие параметры в Direct2D, которые полезны в следующих случаях:
- Граф эффектов зависит от высокой числовой точности или цветов за пределами диапазона [0, 1], и вы хотите убедиться, что они всегда будут доступны
- Или граф эффектов зависит от реализации отрисовки для закрепления промежуточных цветов в диапазоне [0, 1], и вы хотите убедиться, что это зажим всегда происходит.
Direct2D часто разделяет граф эффектов на разделы и отображает каждый раздел в отдельном шаге. Выходные данные некоторых шагов могут храниться в промежуточных текстурах Direct3D, которые по умолчанию имеют ограниченный числовой диапазон и точность. Direct2D не гарантирует, используются ли эти промежуточные текстуры. Это поведение может отличаться в зависимости от возможностей GPU, а также в зависимости от версий Windows.
В Windows 10 Direct2D использует меньше промежуточных текстур из-за использования компоновки шейдеров. Поэтому Direct2D может выдавать другие результаты с параметрами по умолчанию, чем в предыдущих выпусках Windows. Это в первую очередь влияет на сценарии, в которых связывание шейдеров возможно в графе эффектов, и этот граф также содержит эффекты, которые создают цвета вывода в расширенном диапазоне.
Общие сведения о отрисовке эффектов и промежуточных элементах
Для отрисовки графа эффектов Direct2D сначала находит базовый граф "преобразований", где преобразование — это узел графа, используемый в эффекте. Существуют различные типы преобразований, в том числе те, которые предоставляют шейдеры Direct3D для использования Direct2D.
Например, Direct2D может отобразить граф эффектов следующим образом:
Direct2D ищет возможности сокращения числа промежуточных текстур, используемых для отрисовки графа эффектов; эта логика непрозрачна для приложений. Например, следующий граф может быть отрисован с помощью Direct2D с помощью одного вызова рисования Direct3D без промежуточных текстур:
До Windows 10 Direct2D всегда использовал промежуточные текстуры, если в одном графе эффектов использовались несколько шейдеров пикселей. Большинство встроенных эффектов, которые просто корректируют значения цвета (например, яркость или насыщенность), делают это с помощью шейдеров пикселей.
В Windows 10 Direct2D теперь может избежать использования промежуточных текстур в таких случаях. Это делается путем внутренней компоновки смежных пиксельных шейдеров. Пример:
Обратите внимание, что не все смежные пиксельные шейдеры в графе могут быть связаны друг с другом, поэтому только некоторые графы будут выдавать разные выходные данные на Windows 10. Полные сведения см. в разделе Связывание шейдера эффектов. Основные ограничения:
- Эффект не будет связан с эффектами, потребляющими его выходные данные, если первый эффект связан в качестве входных данных с несколькими эффектами.
- Эффект не будет связан с набором эффектов в качестве входных данных, если первый эффект использует входные данные в логической позиции, отличной от его выходных данных. Например, эффект цветовой матрицы может быть связан с его входными данными, но эффект свертки не будет.
Встроенное поведение эффекта
Многие встроенные эффекты могут выдавать цвета за пределами диапазона [0, 1] в непреднастроенном цветовом пространстве, даже если их входные цвета находятся в пределах этого диапазона. В этом случае такие цвета могут быть подвергнуты числовой обрезки. Обратите внимание, что важно учитывать диапазон цветов в непредусмотренных пространствах, даже если встроенные эффекты обычно создают цвета в предварительном пространстве. Это гарантирует, что цвета остаются в пределах диапазона, даже если другие эффекты впоследствии ненапомянуты.
Некоторые эффекты, которые могут выдавать эти цвета вне диапазона, предлагают свойство ClampOutput. К ним относятся следующие объекты.
Установка для свойства ClampOutput значения TRUE для этих эффектов гарантирует, что согласованный результат будет достигнут независимо от таких факторов, как связывание шейдеров. Обратите внимание, что зажим происходит в непределенном пространстве.
Другие встроенные эффекты также могут выдавать выходные цвета за пределами диапазона [0, 1] в непреднастроенном пространстве, даже если их цвета пиксели (и свойства "Цвет", если таковые имеются) находятся в этом диапазоне. К ним относятся следующие объекты.
- Эффекты преобразования и масштабирования (если свойство Режима интерполяции имеет значение Cubic или High Quality Cubic)
- Световые эффекты
- Обнаружение границ (если свойство Overlay Edges имеет значение TRUE)
- Экспозиция
- Composite (если свойство Mode имеет значение Plus)
- Температура и оттенок
- Сепия
- Насыщенность
Принудительное числовая обрезка в графе эффектов
При использовании перечисленных выше эффектов, которые не имеют свойства ClampOutput, приложения должны рассмотреть возможность принудительного цифрового закрепления. Это можно сделать, вставив дополнительный эффект в граф, который зажимает его пиксели. Можно использовать эффект Цветной матрицы, при этом свойству ClampOutput присвоено значение TRUE и свойство ColorMatrix сохраняется как значение по умолчанию (сквозное).
Второй вариант достижения согласованных результатов заключается в том, чтобы Direct2D использовал промежуточные текстуры с большей точностью. Это действие описано ниже.
Управление точностью промежуточных текстур
Direct2D предоставляет несколько способов управления точностью графа. Прежде чем использовать форматы высокой точности в Direct2D, приложения должны убедиться, что они достаточно поддерживаются GPU. Чтобы проверка этого, используйте ID2D1DeviceContext::IsBufferPrecisionSupported.
Приложения могут создавать устройство Direct3D с помощью WARP (программная эмуляция), чтобы гарантировать, что все точность буфера поддерживается независимо от фактического оборудования GPU на устройстве. Это рекомендуется в таких сценариях, как применение эффектов к фотографии при сохранении на диске. Даже если Direct2D поддерживает форматы буферов высокой точности на GPU, в этом сценарии рекомендуется использовать WARP на GPU 9.X из-за ограниченной точности арифметики шейдеров и выборки на некоторых маломощных мобильных GPU.
В каждом из приведенных ниже случаев запрошенная точность фактически является минимальной точностью, используемой Direct2D. Если промежуточные значения не требуются, можно использовать более высокую точность. Direct2D также может совместно использовать промежуточные текстуры для разных частей одного и того же графа или для разных графов. В этом случае Direct2D использует максимальную точность, запрошенную для всех задействованных операций.
Точный выбор из ID2D1DeviceContext::SetRenderingControls
Самый простой способ управления точностью промежуточных текстур Direct2D — использовать ID2D1DeviceContext::SetRenderingControls. Это определяет точность всех промежуточных текстур, если точность не задается вручную для эффектов или преобразований напрямую.
if (Device->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
// Get the current rendering controls
D2D1_RENDERING_CONTROLS renderingControls = {};
Context->GetRenderingControls(&renderingControls);
// Switch the precision within the rendering controls and set it
renderingControls.bufferPrecision = D2D1_BUFFER_PRECISION_32BPC_FLOAT;
Context->SetRenderingControls(&renderingControls);
}
Выбор точности из входных данных и целевых объектов отрисовки
Приложения также могут полагаться на точность входных данных графа эффектов для управления точностью промежуточных текстур. Это верно, если точность буфера не указана с помощью ID2D1DeviceContext::SetRenderingControls и не задается вручную для эффектов и преобразования напрямую.
Точность входных данных эффектов распространяется через граф для выбора точности подчиненных промежуточных значений. Там, где встречаются различные ветви в графе эффектов, используется наибольшая точность любых входных данных.
Точность, выбранная на основе растрового изображения Direct2D, определяется по его формату пикселей. Точность, выбранная для ID2D1ImageSource , определяется из формата пикселей WIC базового объекта IWICBitmapSource, используемого для создания ID2D1ImageSource. Обратите внимание, что Direct2D не позволяет создавать источники изображений с использованием источников WIC с точностью, неподдерживаемой Direct2D и GPU.
Возможно, Direct2D не сможет назначить эффекту точность на основе его входных данных. Это происходит, когда эффект не имеет входных данных или когда используется ID2D1CommandList , который не имеет определенной точности. В этом случае точность промежуточных текстур определяется из растрового рисунка, заданного в качестве текущего целевого объекта отрисовки контекста.
Точный выбор непосредственно на эффекте и преобразованиях
Минимальная точность промежуточных текстур также может быть задана в явных расположениях в графе эффектов. Это рекомендуется только для расширенных сценариев.
Минимальную точность можно задать с помощью свойства для эффекта следующим образом:
if (Device->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
hr = Effect->SetValue(D2D1_PROPERTY_PRECISION, D2D1_BUFFER_PRECISION_32BPC_FLOAT);
}
В реализации эффекта минимальную точность можно задать с помощью ID2D1RenderInfo::SetOutputPrecision следующим образом:
if (EffectContext->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
hr = RenderInfo->SetOutputBuffer(
D2D1_BUFFER_PRECISION_32BPC_FLOAT,
D2D1_CHANNEL_DEPTH_4);
}
Обратите внимание, что набор точности для эффекта будет распространяться на подчиненные эффекты в том же графе эффектов, если для этих нисходящих эффектов не задана другая точность. Точность, заданная для преобразования в рамках эффекта, не влияет на точность подчиненных узлов преобразования.
Ниже приведена полная рекурсивная логика, используемая для определения минимальной точности промежуточного буфера, в котором хранятся выходные данные данного узла преобразования: