数据转换规则

以下部分介绍了 Direct3D 如何处理数据类型之间的转换。

数据类型术语

随后使用以下术语集来描述各种格式转换的特征。

术语 定义
SNORM 带符号规范化整数,这意味着对于 n 位 2 的补数,最大值表示 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 的平均值为 0.0f,所有 1 的平均值为 1.0f。 表示从 0.0f 到 1.0f 的均匀间距浮点值序列。 例如,2 位 UNORM 表示 0.0f、1/3、2/3 和 1.0f。
SINT 带符号整数。 2 的补数整数。 例如,3 位 SINT 表示整型值 -4、-3、-2、-1、0、1、2、3。
UINT 无符号整数。 例如,3 位 UINT 表示整型值 0、1、2、3、4、5、6、7。
Direct3D 定义的任何表示形式的浮点值。
SRGB 与 UNORM 类似,对于 n 位数字,所有 0 的平均值为 0.0f,所有 1 的平均值为 1.0f。 但是,与 UNORM 不同,SRGB 将所有 0 到所有 1 之间的无符号整数编码序列表示数字浮点解释中的非线性进展,介于 0.0f 到 1.0f 之间。 大致而言,如果这种非线性进展(SRGB)显示为颜色序列,它将在“平均”的观看条件下显示为“平均”观察者的亮度水平线性渐变。 有关完整的详细信息,请参阅 IEC (国际 Gbt 委员会)的 SRGB 颜色标准 IEC 61996-2-1。

 

浮点转换

每当发生不同表示形式之间的浮点转换(包括非浮点表示形式)时,以下规则适用。

从更高的范围表示形式到较低的范围表示形式

  • 在转换为另一种浮点格式的过程中,使用舍入到零。 如果目标为整数或固定点格式,则使用舍入到最接近的偶数格式,除非显式记录转换为使用另一个舍入行为,例如将 FLOAT 转换为 SNORM、FLOAT 到 UNORM 或 FLOAT 到 SRGB。 其他例外是 ftoi 和 ftou 着色器指令,它们使用舍入到零。 最后,纹理采样器和光栅器使用的浮点到固定转换具有从无限精确理想到单位Last-Place 中测量的指定容差。
  • 对于大于较低范围目标格式的动态范围的源值(例如,将较大的 32 位浮点值写入 16 位浮点 RenderTarget),最大可表示值(适当有符号)值结果,不包括有符号无穷大(由于上述舍入到零)。
  • 如果 NaN 表示形式以较低的范围格式存在,则采用较高范围格式的 NaN 将转换为 NaN 表示形式。 如果较低格式没有 NaN 表示形式,则结果将为 0。
  • 如果可用,则采用较高范围格式的 INF 将转换为较低范围格式的 INF。 如果较低格式没有 INF 表示形式,则会将其转换为可表示的最大值。 如果目标格式可用,将保留该符号。
  • 如果以较低的范围格式提供,则较高范围格式的 Denorm 将转换为较低范围格式的 Denorm 表示形式,并且转换是可能的,否则结果为 0。 如果目标格式可用,将保留签名位。

从较低的范围表示形式转换为更高的范围表示形式

  • 如果以较高范围格式提供,则较低范围格式的 NaN 将转换为较高范围格式的 NaN 表示形式。 如果更高的范围格式没有 NaN 表示形式,它将转换为 0。
  • 如果以较高范围格式提供,则采用较低范围格式的 INF 将转换为采用较高范围格式的 INF 表示形式。 如果较高格式没有 INF 表示形式,则会将其转换为可表示的最大值(MAX_FLOAT采用该格式)。 如果目标格式可用,将保留该符号。
  • 如果可能,较低范围格式的 Denorm 将转换为较高范围格式的规范化表示形式,否则,如果 Denorm 表示形式存在,则转换为具有较高范围格式的 Denorm 表示形式。 如果更高的范围格式没有 Denorm 表示形式,则失败这些格式将转换为 0。 如果目标格式可用,将保留该符号。 请注意,32 位浮点数计数为没有 Denorm 表示形式的格式(因为 32 位浮点刷新作中的 Denorms 用于对保留的 0 进行签名)。

整数转换

下表介绍了从上述各种表示形式转换为其他表示形式。 仅显示 Direct3D 中实际发生的转换。

源数据类型 目标数据类型 转换规则
SNORM 给定表示有符号范围 [-1.0f 到 1.0f] 的 n 位整数值,则转换为浮点如下所示。
  • 最负值映射到 -1.0f。 例如,5 位值 10000 映射到 -1.0f。
  • 所有其他值都转换为浮点数(调用它 c),然后结果 = c * (1.0f / (2⁽ⁿ⁻ー⁾-1) 。 例如,5 位值 10001 转换为 -15.0f,然后除以 15.0f,生成 -1.0f。
SNORM 给定浮点数,转换为表示有符号范围 [-1.0f 到 1.0f] 的 n 位整数值如下所示。
  • 让 c 表示起始值。
  • 如果 c 为 NaN,则结果为 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 Unit-Last-Place(整数端)。 这意味着,从浮点数转换为整数刻度后,允许将可表示的目标格式值的 D3Dxx 中的任何值_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place 映射到该值。 额外的数据可逆性要求可确保转换在整个范围内不可声明,并且所有输出值都可实现。 (在此处所示的常量中,xx 应替换为 Direct3D 版本,例如 10、11 或 12。
UNORM 起始 n 位值转换为浮点值(0.0f、1.0f、2.0f 等),然后除以 (2ⁿ-1)。
UNORM 让 c 表示起始值。
  • 如果 c 为 NaN,则结果为 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 Unit-Last-Place(整数端)。 这意味着,从浮点数转换为整数刻度后,允许将可表示的目标格式值的 D3Dxx 中的任何值_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place 映射到该值。 额外的数据可逆性要求可确保转换在整个范围内不可声明,并且所有输出值都可实现。
SRGB 下面是理想的 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,否则: 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 Unit-Last-Place(在 SRGB 端)。
SRGB 下面是理想的 FLOAT -> SRGB 转换。
假设目标 SRGB 颜色组件有 n 位:
  • 假设起始值为 c。
  • 如果 c 为 NaN,则结果为 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,否则: 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 Unit-Last-Place(整数端)。 这意味着,从浮点数转换为整数刻度后,允许将可表示的目标格式值的 D3Dxx 中的任何值_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place 映射到该值。 额外的数据可逆性要求可确保转换在整个范围内不可声明,并且所有输出值都可实现。
SINT 具有更多位的 SINT 若要从 SINT 转换为具有更多位的 SINT,起始编号的最有效位(MSB)是“签名扩展”到目标格式提供的其他位。
UINT 具有更多位的 SINT 若要从 UINT 转换为具有更多位的 SINT,该数字将复制到目标格式的最小有效位(LSB)和附加 MSB 中填充 0。
SINT 具有更多位的 UINT 若要使用更多位从 SINT 转换为 UINT:如果为负数,该值将固定为 0。 否则,该数字将复制到目标格式的 LSB,其他 MSB 填充为 0。
UINT 具有更多位的 UINT 若要使用更多位从 UINT 转换为 UINT,数字将复制到目标格式的 LSB,并且其他 MSB 填充了 0。
SINT 或 UINT SINT 或 UINT 的位数更少或相等 若要从 SINT 或 UINT 转换为具有更少或相等位的 SINT 或 UINT(以及/或更改有符号性),起始值只是固定到目标格式的范围。

 

固定点整数转换

固定点整数只是某些位大小的整数,具有固定位置的隐式小数点。

无处不在的“integer”数据类型是固定点整数的一种特殊情况,该整数的十进制值位于数字末尾。

固定点数表示形式为:i.f,其中 i 是整数位数,f 是小数位数。 例如 16.8 表示 16 位整数,后跟 8 位分数。 整数部分存储在 2 的补数中,至少如此处定义的那样(不过也可以为无符号整数同样定义)。 小数部分以无符号形式存储。 小数部分始终表示两个最接近整数值之间的正分数,从最负值开始。

对固定点数执行加法和减法运算只是使用标准整数算术,而不考虑隐式小数的位置。 将 1 添加到 16.8 固定点数意味着添加 256,因为小数位数是从数字最不重要的末尾算起的 8 个位置。 其他运算(如乘法)也可使用整数算术来执行,前提是对固定小数的影响被考虑在内。 例如,使用整数乘法将两个 16.8 整数相乘会产生 32.16 结果。

Direct3D 中的两种方式使用固定点整数表示形式。

  • 光栅器中剪裁后的顶点位置贴靠到固定点,以在 RenderTarget 区域中统一分布精度。 许多光栅器作(包括人脸剔除)在固定点贴靠位置上发生,而其他作(如属性内插器设置)则使用已从固定点贴靠位置转换回浮点的位置。
  • 采样作的纹理坐标贴靠到固定点(按纹理大小缩放后),以在选择筛选器点击位置/权重时统一分布纹理空间的精度。 在执行实际筛选算术之前,权重值将转换回浮点。
源数据类型 目标数据类型 转换规则
固定点整数 下面是将浮点数 n 转换为固定点整数 i.f 的常规过程,其中 i 是 (signed) 整数位的数目,f 是小数位数。
  • Compute FixedMin = -2⁽ⁱ⁻ー⁾
  • Compute FixedMax = 2⁽ⁱ⁻ー⁾ - 2(-f)
  • 如果 n 为 NaN,则结果 = 0;如果 n 为 +Inf,则结果 = FixedMax*2f;如果 n 为 -Inf,则结果 = FixedMin*2f
  • 如果 n >= FixedMax,则 result = Fixedmax*2f;如果 n <= FixedMin,则结果 = FixedMin*2f
  • 否则计算 n*2f 并转换为整数。
允许实现在整数结果中使用 D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place 容差,而不是在上述最后一步之后的无限精确值 n*2f
固定点整数 假设要转换为 float 的特定固定点表示形式不包含总共 24 位信息,其中不超过 23 位(在小数部分)。 假设给定的固定点数 fxp 采用 i.f 形式(i 位整数、f 位分数)。 转换为 float 类似于以下伪代码。
float result = (float)(fxp >> f) + // extract integer
((float)(fxp & (2f - 1)) / (2f):提取分数

 

资源(Direct3D 10)