Поделиться через


Правила преобразования данных

В следующих разделах описано, как Direct3D обрабатывает преобразования между типами данных.

Терминология типов данных

В дальнейшем термины из следующего набора используются для описания преобразований различных форматов.

Термин Определение
SNORM Нормализованное целое число со знаком, то есть для n-разрядного числа в дополнительном коде максимальное значение означает 1,0f (например, 5-разрядное значение 01111 сопоставляется с 1,0f), а минимальное значение означает -1,0f (например, 5-разрядное значение 10000 сопоставляется с -1,0f). Кроме того, второе после минимального число сопоставляется с -1,0f (например, 5-разрядное значение 10001 сопоставляется с -1,0f). Таким образом, существует два представления целых чисел для -1,0f. Для 0,0f и 1,0f существует по одному представлению. В результате получается набор представлений целых чисел для равномерно распределенных значений с плавающей точкой в диапазоне от -1,0f до 0,0f и дополнительный набор представлений для чисел в диапазоне от 0,0f до 1,0f
UNORM Нормализованное целое число без знака, то есть для n-разрядного числа все нули означают 0,0f, а все единицы — 1,0f. Представлена последовательность равномерно распределенных значений с плавающей точкой от 0,0f до 1,0f. Например, 2-разрядное число UNORM представляет 0,0f, 1/3, 2/3 и 1,0f.
SINT Целое число со знаком. Целое число в дополнительном коде. Например, 3-разрядное число SINT представляет целочисленные значения -4, -3, -2, -1, 0, 1, 2, 3.
UINT Целое число без знака. Например, 3-разрядное число UINT представляет целочисленные значения 0, 1, 2, 3, 4, 5, 6, 7.
FLOAT Значение с плавающей точкой в любом из представлений, определенных Direct3D.
SRGB Аналог UNORM в том смысле, что для n-разрядного числа все нули означают 0,0f, а все единицы — 1,0f. Но в случае с SRGB, в отличие от UNORM, последовательность целочисленных кодировок без знака в диапазоне между всеми нулями и всеми единицами представляет нелинейную последовательность в интерпретации чисел с плавающей точкой в диапазоне от 0,0f до 1,0f. Грубо говоря, если нелинейная последовательность SRGB отображается как последовательность цветов, для "среднего" наблюдателя при "средних" условиях просмотра на "среднем" дисплее она будет выглядеть, как линейный набор уровней яркости. Полные сведения см. в цветовом стандарте SRGB IEC 61996-2-1 на сайте Международной электротехнической комиссии (IEC).

 

Преобразование с плавающей точкой

При выполнении преобразования с плавающей точкой между разными представлениями, включая представления без плавающей точки, действуют следующие правила.

Преобразование из представления верхнего диапазона в представление нижнего диапазона

  • При преобразовании в другой формат с плавающей точкой используется округление к нулю Если целевое значение является целым числом или числом с плавающей точкой, используется округление до ближайшего четного числа, если в описании преобразования явно не указана необходимость использования другого метода округления, такого как округление к ближайшему при преобразовании из FLOAT в SNORM, из FLOAT в UNORM или из FLOAT в SRGB Исключениями также являются инструкции шейдеров ftoi и ftou, в которых используется округление к нулю. Наконец, для преобразований чисел с плавающей точкой в числа с фиксированной точкой, используемых текстурным дискретизатором и средством прорисовки, указывается допуск от бесконечно точного идеала, измеряемый единицей наименьшей точности.
  • Для исходных значений, превышающих динамический диапазон целевого формата нижнего диапазона (например, большое 32-разрядное значение с плавающей точкой записывается в 16-разрядный float RenderTarget), максимальное изобразимое (соответствующим образом подписанное) значение, НЕ включая бесконечность со знаком (из-за округления до нуля, описанного выше).
  • Не число в формате верхнего диапазона преобразуется в представление не числа в формате нижнего диапазона, если представление не числа существует в формате нижнего диапазона. Если в формате нижнего диапазона нет представления не числа, результатом будет 0.
  • Бесконечное число в формате верхнего диапазона преобразуется в бесконечное число в формате нижнего диапазона, если возможно. Если в формате нижнего диапазона нет представления бесконечного числа, оно преобразуется в максимальное представляемое значение. Знак будет сохранен, если он доступен в конечном формате.
  • Денормализованное число в формате верхнего диапазона преобразуется в представление денормализованного числа в формате нижнего диапазона, если оно есть в формате нижнего диапазона и преобразование возможно. В противном случае результатом будет 0. Бит знака будет сохранен, если он доступен в конечном формате.

Преобразование из представления нижнего диапазона в представление верхнего диапазона

  • Не число в формате нижнего диапазона преобразуется в представление не числа в формате верхнего диапазона, если оно доступно в формате верхнего диапазона. Если в формате верхнего диапазона нет представления не числа, оно преобразуется в 0.
  • Бесконечное число в формате нижнего диапазона преобразуется в представление бесконечного числа в формате верхнего диапазона, если оно доступно в формате верхнего диапазона. Если более высокий формат не имеет представления INF, он будет преобразован в максимально допустимое значение (MAX_FLOAT в этом формате). Знак будет сохранен, если он доступен в конечном формате.
  • Денормализованное число в формате нижнего диапазона преобразуется в нормализованное представление в формате верхнего диапазона, если это возможно, или в представление денормализованного числа в формате верхнего диапазона при наличии такого представления. Если ни одну из этих операций не удается выполнить из-за отсутствия представления денормализованного числа в формате верхнего диапазона, число преобразуется в 0. Знак будет сохранен, если он доступен в конечном формате. Обратите внимание, что 32-разрядные числа с плавающей точкой считаются форматом без представления денормализованного числа, так как денормализованные числа в операциях с 32-разрядными числами с плавающей точкой приводятся к нулю с сохранением знака.

Преобразование целых чисел

В следующей таблице описаны преобразования из различных описанных выше представлений в другие представления. Показаны только преобразования, которые фактически происходят в Direct3D.

Тип исходных данных Тип конечных данных Правило преобразования
SNORM FLOAT Преобразование n-разрядного целочисленного значения, представляющего диапазон со знаком [от -1,0f до 1,0f], в число с плавающей точкой происходит следующим образом.
  • Наименьшее отрицательное значение сопоставляется с -1,0f. Например, 5-разрядное значение 10000 сопоставляется с - 1,0f.
  • Все остальные значение преобразуются в числа с плавающей точкой (назовем их c), а результат вычисляется по формуле c * (1,0f / (2⁽ⁿ⁻¹⁾-1)). Например, 5-разрядное значение 10001 преобразуется в -15,0f и делится на 15,0f — в результате получается -1,0f.
FLOAT SNORM Преобразование числа с плавающей точкой в n-разрядное целочисленное значение, представляющее диапазон со знаком [от -1,0f до 1,0f], происходит следующим образом.
  • Пусть c представляет начальное значение.
  • Если c не число, результатом будет 0.
  • Если c > 1.0f, включая INF, он зажимается до 1.0f.
  • Если c < -1.0f, включая -INF, он зажимается до -1,0f.
  • Преобразование из шкалы чисел с плавающей точкой в шкалу целых чисел: c = c * (2ⁿ⁻¹-1).
  • Преобразование в целое число происходит следующим образом.
    • Если c >= 0, то c = c + 0,5f, в противном случае c = c - 0,5f.
    • Десятичная дробь опускается, а оставшееся значение с плавающей точкой (целочисленное) напрямую преобразуется в целое число.
Для этого преобразования разрешается допуск в виде единицы наименьшей точности D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_Unit-Last-Place (с целочисленной стороны). Это значит, что после преобразования из шкалы чисел с плавающей точкой в целочисленную шкалу любое значение в пределах единицы наименьшей точности D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP представляемого значения конечного формата может быть сопоставлено с этим значением. Дополнительное требование к обратимости данных гарантирует, что преобразование остается неубывающим в пределах всего диапазона, а все выходные значения — достигаемыми. (В указанных здесь константах xx следует заменить версией Direct3D, например 10, 11 или 12.)
UNORM FLOAT Начальное n-разрядное значение преобразуется в число с плавающей точкой (0,0f, 1,0f, 2,0f и т. д.), а затем делится на (2ⁿ-1).
FLOAT UNORM Пусть c представляет начальное значение.
  • Если c не число, результатом будет 0.
  • Если c > 1.0f, включая INF, он зажимается до 1.0f.
  • Если c < 0,0f, включая -INF, он зажимается до 0,0f.
  • Преобразование из шкалы чисел с плавающей точкой в шкалу целых чисел: c = c * (2ⁿ-1).
  • Преобразование в целое число.
    • c = c + 0,5f.
    • Десятичная дробь опускается, а оставшееся значение с плавающей точкой (целочисленное) напрямую преобразуется в целое число.
Для этого преобразования разрешается допуск в виде единицы наименьшей точности D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP (с целочисленной стороны). Это значит, что после преобразования из шкалы чисел с плавающей точкой в целочисленную шкалу любое значение в пределах единицы наименьшей точности D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP представляемого значения конечного формата может быть сопоставлено с этим значением. Дополнительное требование к обратимости данных гарантирует, что преобразование остается неубывающим в пределах всего диапазона, а все выходные значения — достигаемыми.
SRGB FLOAT Ниже описано идеальное преобразование SRGB в FLOAT.
  • Возьмем начальное n-разрядное значение, преобразуем его в целое число (0,0f, 1,0f, 2,0f и т. д.); результат обозначим c.
  • c = c * (1,0f / (2ⁿ-1))
  • Если (c < = D3Dxx_SRGB_TO_FLOAT_THRESHOLD) то: result = c / D3Dxx_SRGB_TO_FLOAT_DENOMINATOR_1, else: result = ((c + D3Dxx_SRGB_TO_FLOAT_OFFSET)/D3Dxx_SRGB_TO_FLOAT_DENOMINATOR_2)D3Dxx_SRGB_TO_FLOAT_EXPONENT
Для этого преобразования разрешается допуск в виде единицы наименьшей точности D3Dxx_SRGB_TO_FLOAT_TOLERANCE_IN_ULP (со стороны SRGB).
FLOAT SRGB Ниже приведено идеальное преобразование FLOAT-> SRGB.
При условии, что конечный цветовой компонент SRGB содержит n бит.
  • Пусть c — это начальное значение.
  • Если c не число, результатом будет 0.
  • Если c > 1.0f, включая INF, зажимается до 1,0f.
  • Если c < 0,0f, включая -INF, он зажимается до 0,0f.
  • Если (c <= D3Dxx_FLOAT_TO_SRGB_THRESHOLD), то: c = D3Dxx_FLOAT_TO_SRGB_SCALE_1 * c, else: c = D3Dxx_FLOAT_TO_SRGB_SCALE_2 * c(D3Dxx_FLOAT_TO_SRGB_EXPONENT_NUMERATOR/D3Dxx_FLOAT_TO_SRGB_EXPONENT_DENOMINATOR) - D3Dxx_FLOAT_TO_SRGB_OFFSET
  • Преобразование из шкалы чисел с плавающей точкой в шкалу целых чисел: c = c * (2ⁿ-1).
  • Преобразование в целое число:
    • c = c + 0,5f.
    • Десятичная дробь опускается, а оставшееся значение с плавающей точкой (целочисленное) напрямую преобразуется в целое число.
Для этого преобразования разрешается допуск в виде единицы наименьшей точности D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP (с целочисленной стороны). Это значит, что после преобразования из шкалы чисел с плавающей точкой в целочисленную шкалу любое значение в пределах единицы наименьшей точности D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP представляемого значения конечного формата может быть сопоставлено с этим значением. Дополнительное требование к обратимости данных гарантирует, что преобразование остается неубывающим в пределах всего диапазона, а все выходные значения — достигаемыми.
SINT SINT с дополнительным числом бит Чтобы преобразовать SINT в SINT с дополнительными битами, наиболее значимым битом (MSB) начального числа является "расширение знака" до дополнительных битов, доступных в целевом формате.
UINT SINT с дополнительным числом бит Для преобразования SINT в SINT с дополнительным числом бит число копируется в младшие разряды (LSB) конечного формата, а дополнительные старшие разряды заполняются нулями.
SINT UINT с дополнительным числом бит Для преобразования SINT в UINT с дополнительным числом бит значение прикрепляется к 0, если оно отрицательное. В противном случае число копируется в младшие разряды конечного формата, а дополнительные старшие разряды заполняются нулями.
UINT UINT с дополнительным числом бит Для преобразования UINT в UINT с дополнительным числом бит число копируется в младшие разряды конечного формата, а дополнительные старшие разряды заполняются нулями.
SINT или UINT SINT или UINT с дополнительным или одинаковым числом бит Для преобразования SINT или UINT в SINT или UINT с дополнительным или одинаковым числом бит (или изменения наличия знака) начальное значение прикрепляется к диапазону конечного формата.

 

Преобразование целого числа с фиксированной точкой

Целые числа с фиксированной точкой — это целые числа некоторой разрядности с неявным десятичным разделителем в фиксированном расположении.

Распространенный "целочисленный" тип данных — это особый случай целого числа с фиксированной точкой и десятичным числом в конце.

Представления чисел с фиксированной точкой характеризуются как i.f, где i — количество целочисленных бит, а f — дробных бит. Например, 16,8 означает, что за 16 целочисленными битами следуют 8 дробных бит. Целочисленная часть хранится в дополнительном коде, по крайней мере согласно данному здесь определению. Впрочем, для целых чисел без знака можно использовать аналогичное определение. Дробная часть хранится без знака. Дробная часть всегда представляет положительную дробь между двумя ближайшими целочисленными значениями, начиная с наименьшего отрицательного.

Операции сложения и вычитания над числами с фиксированной точкой выполняются с помощью стандартных арифметических действий над целыми числами без учета расположения неявного десятичного разделителя. Добавление 1 к числу с фиксированной точкой 16,8 означает лишь добавление 256, так как десятичный разделитель находится в 8 битах от младшего разряда числа. Другие операции, например умножение, могут также выполняться с помощью арифметических действий над целыми числами, но в этом случае следует учитывать влияние на фиксированный десятичный разделитель. Например, в результате умножения двух целых чисел 16,8 с помощью действия умножения целых чисел получается 32,16.

Представления целых чисел с фиксированной точкой используются в Direct3D двумя способами.

  • Положения вершин после отсечения в средстве прорисовки прикрепляются к фиксированной точке для равномерного распределения точности в области RenderTarget. Многие операции средства прорисовки, включая, например, выбор передней поверхности, выполняются над положениями, прикрепленными к фиксированной точке, а в некоторых операциях, таких как настройка интерполятора атрибутов, используются положения, преобразованные в число с плавающей точкой из положений, прикрепленных к фиксированной точке.
  • Координаты текстуры для операций дискретизации прикрепляются к фиксированной точке (после масштабирования по размеру текстуры) для равномерно распределения точности в области текстуры при выборе расположения и веса блоков задержки фильтра. Значения веса преобразуются в числа с плавающей точкой перед выполнением сами арифметических действий для фильтрации.
Тип исходных данных Тип конечных данных Правило преобразования
FLOAT Целое число с фиксированной точкой Ниже приведена общая процедура преобразования числа с плавающей точкой n в целое число с фиксированной точкой i.f, где i — количество целочисленных бит (со знаком), а f — количество дробных бит.
  • Вычисляем FixedMin = -2⁽ⁱ⁻¹⁾
  • Вычисление FixedMax = 2⁽ⁱ⁻¹⁾ - 2(-f)
  • Если n является NaN, результат = 0; Если n имеет значение +Inf, результат = FixedMax*2f; Если n имеет значение -Inf, result = FixedMin*2f
  • Если n >= FixedMax, result = Fixedmax*2f; если n <= FixedMin, result = FixedMin*2f
  • Иначе вычисляем n*2f и преобразуем результат в целое число.
Для целочисленного результата реализаций разрешается допуск в виде единицы наименьшей точности D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP вместо бесконечно точного значения n*2f после последнего указанного выше действия.
Целое число с фиксированной точкой FLOAT Предположим, что определенное представление с фиксированной точкой, преобразуемое в число с плавающей точкой, содержит не более 24 бит информации, из которых не более 23 бит относятся к дробному компоненту. Предположим, что данное число с фиксированной точкой, fxp, имеет форму i.f (i целочисленных бит, f дробных бит). Преобразование в число с плавающей точкой похоже на следующий псевдокод.
float result = (float)(fxp >> f) + // extract integer
((float)(fxp & (2f - 1)) / (2f)); извлечение дроби

 

Ресурсы (Direct3D 10)