データ変換ルール

次のセクションでは、Direct3D がデータ型の間の変換を処理する方法について説明します。

データ型に関する用語

次に示す用語は、さまざまな形式の変換の特性を説明するために後で使用されます。

項目 定義
SNORM 符号付き正規化整数。n ビットの 2 の補数をとり、最大値は 1.0f で (たとえば、5 ビット値 01111 は 1.0f にマップされます)、最小値は -1.0f です (たとえば、5 ビット値 10000 は -1.0f にマップされます)。 さらに、2 番目に小さい数値も -1.0f にマップされます (たとえば、5 ビット値 10001 は -1.0f にマップされます)。 したがって、-1.0f には 2 つの整数表現があります。 0.0f の整数表現は 1 つで、1.0f の整数表現も 1 つです。 その結果、-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 を表します。
FLOAT Direct3D で定義された任意の表現の浮動小数点値。
SRGB n ビットの数値ですべての桁が 0 の場合は 0.0f、すべての桁が 1 の場合は 1.0f を表す点で UNORM と同様です。 ただし、UNORM とは異なり、SRGB では、すべての桁が 0 である値からすべての桁が 1 である値までの符号なし整数エンコードのシーケンスは、0.0f ~ 1.0f の数値の浮動小数点で表した値に対して非線形数列を表します。 大まかにいえば、この非線形の数列である SRGB をカラーのシーケンスとして表示すると、平均的な視聴者には、平均的な表示条件下および平均的なディスプレイ上で、輝度レベルの直線的な変化に見えます。 詳細については、IEC (国際電気標準会議) の SRGB カラー規格である IEC 61996-2-1 を参照してください。

 

浮動小数点の変換

浮動小数点以外の表現との変換を含め、さまざまな表現間で浮動小数点の変換が発生する場合、必ず以下の規則を適用します。

範囲が広い表現から範囲が狭い表現への変換

  • 別の浮動小数点形式への変換時には、ゼロへの丸めを使用します。 変換先が整数または固定小数点形式の場合、最も近い偶数への丸めを使用します。ただし、FLOAT から SNORM、FLOAT から UNORM、FLOAT から SRGB の各変換で使用する最も近い値への丸めなどのように、別の丸め動作を使用した変換が明示されている場合は除きます。 その他の例外としてシェーダー命令の ftoi と ftou があります。この場合は、ゼロへの丸めを使用します。 最後に、テクスチャーのサンプラーとラスタライザーで使用する浮動小数点から固定小数点への変換では、無限に理想的な精度に対する指定の許容誤差があります。この許容誤差は、ULP (Unit-Last-Place) で表します。
  • より低い範囲のターゲット形式のダイナミック レンジより大きいソース値の場合 (たとえば、32 ビットの大きな float 値が 16 ビット float RenderTarget に書き込まれます)、表現可能な (適切に符号付き) 値の最大値は、符号付き無限大を含まない (前述の 0 への丸めによる) 結果になります。
  • 範囲が広い形式にある NaN を範囲の狭い形式に変換する場合、範囲が狭い変換先の形式に該当の NaN 表現があればその表現に変換されます。 範囲が狭い変換先の形式に NaN 表現がない場合、結果は 0 になります。
  • 範囲が広い形式にある INF を範囲が狭い形式に変換する場合、範囲が狭い変換先の形式に該当の INF があればその INF に変換されます。 範囲が狭い変換先の形式に INF 表現がない場合、表現可能な最大の値に変換されます。 変換先の形式で利用可能な場合、符号は保持されます。
  • 範囲が広い形式にある非正規化数を範囲が狭い形式に変換する場合、その変換先の形式に非正規化表現があり、その表現への変換が可能であれば、該当の非正規化表現に変換されます。それ以外の場合、結果は 0 になります。 変換先の形式で利用可能な場合、符号ビットは保持されます。

範囲が狭い表現から範囲が広い表現への変換

  • 範囲が狭い形式にある NaN を範囲の広い形式に変換する場合、範囲が広い変換先の形式で利用可能であれば該当する NaN 表現に変換されます。 範囲が広い形式に NaN 表現がない場合は、0 に変換されます。
  • 範囲が狭い形式にある INF を範囲の広い形式に変換する場合、範囲が広い変換先の形式で利用可能であれば該当する INF 表現に変換されます。 範囲が広い形式に INF 表現がない場合、表現可能な最大の値 (その形式の MAX_FLOAT) に変換されます。 変換先の形式で利用可能な場合、符号は保持されます。
  • 範囲が狭い形式にある非正規化数を範囲が広い形式に変換する場合、変換先の形式の正規化表現に変換可能であれば、その表現に変換されます。変換が不可能な場合、範囲が広い形式に該当の非正規化表現があれば、その表現に変換されます。 範囲が広い形式に非正規化表現がなければ、0 に変換されます。 変換先の形式で利用可能な場合、符号は保持されます。 32 ビット浮動小数点型の数値は、非正規化表現のない形式として扱います (32 ビット浮動小数点型の演算における非正規化数を、符号が保持された 0 にフラッシュする必要があるからです)。

整数の変換

次の表で、前述のさまざまな表現から別の表現への変換について説明します。 ここでは、Direct3D で実際に発生する変換のみを示します。

変換元のデータ型 変換先のデータ型 変換規則
SNORM FLOAT 符号付きの -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 となります。
FLOAT SNORM 浮動小数点値から符号付きの -1.0f ~ 1.0f の範囲を表す n ビットの整数値への変換は次のとおりです。
  • 変換元の値を c とします。
  • c が NaN の場合、結果は 0 です。
  • C > INF を含む 1.0f の場合、1.0f にクランプされます。
  • c < -INF を含む -1.0f の場合、-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 ULP の誤差が許容されます。 つまり、浮動小数点スケールから整数スケールへの変換後、変換先の表現可能な形式の値に対して D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP ULP 以内にある値はすべてその変換先の値にマップできます。 また、データ可換性の要件により、変換は範囲全体にわたって非減少であること、およびすべての出力値が達成可能であることが保証されます。 ここで示した定数で、xx は Direct3D のバージョン (10、11、12 など) に置き換える必要があります。
UNORM FLOAT 変換元の n ビット値は浮動小数点型 (0.0f、1.0f、2.0f など) に変換された後、(2ⁿ-1) で除算されます。
FLOAT UNORM 変換元の値を c とします。
  • c が NaN の場合、結果は 0 です。
  • C > INF を含む 1.0f の場合、1.0f にクランプされます。
  • c < 0.0f (-INF を含む) の場合、0.0f にクランプされます。
  • 次のように浮動小数点のスケールから整数のスケールに変換します。c = c * (2ⁿ-1)。
  • 整数値に変換します。
    • c = c + 0.5f。
    • 小数部を除外し、残りの浮動小数点値 (整数値) を整数に直接変換します。
この変換では、整数側で D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP ULP の誤差が許容されます。 つまり、浮動小数点スケールから整数スケールへの変換後、変換先の表現可能な形式の値に対して D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP 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
この変換では、SRGB 側で D3Dxx_SRGB_TO_FLOAT_TOLERANCE_IN_ULP ULP の誤差が許容されます。
FLOAT SRGB 理想的な FLOAT -> SRGB 変換を次に示します。
変換先の SRGB カラー成分を n ビットと仮定します。
  • 変換元の値を c とします。
  • c が NaN の場合、結果は 0 です。
  • C > INF を含む 1.0f の場合、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 ULP の誤差が許容されます。 つまり、浮動小数点スケールから整数スケールへの変換後、変換先の表現可能な形式の値に対して D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP ULP 以内にある値はすべてその変換先の値にマップできます。 また、データ可換性の要件により、変換は範囲全体にわたって非減少であること、およびすべての出力値が達成可能であることが保証されます。
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 に変換 (符号の有無の変更を伴うことも可) する場合、変換元の値が変換先の形式の範囲に単純にクランプされます。

 

固定小数点整数の変換

固定小数点整数とは単に、暗黙の小数点が固定位置にある一定のビット長の整数です。

よく使用される "整数" データ型は、数値の末尾に小数点を置いた、固定小数点整数の特殊なケースです。

固定小数点数は i.f という形式で表現します。i は整数部ビット数、f は小数部ビット数を表します。 たとえば、16.8 は 16 ビットの整数の後ろに 8 ビットの小数が続くことを示します。 整数部は、少なくともここでの定義では、2 の補数として格納されます (符号なし整数についても同様です)。 小数部は符号なしの形式で格納されます。 小数部は、負数側の最小値から、互いに最も近い 2 つの整数値の間で必ず正の小数となります。

固定小数点数に対する加算演算および減算演算は、単純に通常の整数演算で実行します。暗黙の小数点の位置は考慮されません。 16.8 の固定小数点数に対する 1 の加算は、この数値の最下位端から 8 桁は小数部であるため、256 を加算することを意味します。 乗算などのその他の演算も、固定小数点への影響を考慮したうえで、単純に整数演算によって実行できます。 たとえば、2 つの 16.8 の整数を整数乗算すると、結果は 32.16 になります。

Direct3D では、次の 2 つの状況で固定小数点整数表現を使用します。

  • ラスタライザーでのクリップ後の頂点位置は固定小数点にスナップされ、RenderTarget 領域全体で精度分布が均一になります。 面のカリングをはじめ、多くのラスタライザー処理は固定小数点のスナップ位置で発生しますが、属性のインターポレーター セットアップなどの処理では、固定小数点のスナップ位置から浮動小数点に逆変換した位置を使用します。
  • フィルターのタップ位置/重みの選択では、サンプリング処理のテクスチャー座標が (テクスチャー サイズに合わせてスケーリングされた後) 固定小数点にスナップされ、テクスチャー領域全体で精度分布が均一になります。 重み値は、実際のフィルタリング演算を実行する前に浮動小数点に逆変換します。
変換元のデータ型 変換先のデータ型 変換規則
FLOAT 固定小数点整数 浮動小数点型の数値 n を固定小数点整数 i.f に変換する一般的な手順は次のとおりです。ここで、i は整数部ビット数 (符号付き)、f は小数部ビット数です。
  • FixedMin = -2⁽ⁱ⁻¹⁾ を計算します。
  • FixedMax = 2⁽ⁱ⁻¹⁾ - 2(-f) を計算します。
  • n が NaN の場合、結果は 0 です。n が +Inf の場合の結果は FixedMax*2f で、n が -Inf の場合の結果は FixedMin*2f です。
  • n >= FixedMax の場合、result = Fixedmax*2f;n <= FixedMin の場合、result = FixedMin*2f
  • それ以外の場合は、n*2f を計算して整数に変換します。
実装では、上の最後の手順で得られた整数と無限大精度値 n*2f との比較で、D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP ULP の誤差が許容されます。
固定小数点整数 FLOAT 浮動小数点型に変換する固定小数点表現があり、その合計ビット数は 24 ビット以下で、うち小数部は 23 ビット以下であるとします。 特定の固定小数点数 fxp を i.f の形式とします (i ビットの整数、f ビットの小数)。 浮動小数点型への変換は次に示す疑似コードのようになります。
float result = (float)(fxp >> f) + // extract integer
((float)(fxp & (2f - 1)) / (2f));分数の抽出

 

リソース (Direct3D 10)