Version: 2023.1
言語: 日本語
ビルトインのシェーダー変数
サンプラー状態の利用

シェーダーのデータ型と精度

Unity は標準的なシェーダー言語 HLSL を使用しており、一般的な HLSL のデータ型をサポートしています。ただし、Unity はモバイルプラットフォームでのサポートを向上させるために、一部のデータ型を HLSL とは異なる方法で処理します。

基本的なデータ型

Shaders carry out the majority of calculations using floating point numbers (also called as float in regular programming languages like C#). In Unity’s implementation of HLSL, the scalar floating point data types are float and half. These data types differ in precision and, consequently, performance or power usage. There are also several related data types for vectors and matrices such as half3 and float4x4.

高精度: float

これは最高精度の浮動小数点データ型です。ほとんどのプラットフォームでは、float 値は通常のプログラミング言語と同様に 32 ビットです。

完全な float 精度は通常、ワールド空間の位置やテクスチャ座標、または三角関数や累乗/指数計算のような複雑な関数を含むスカラー計算に有用です。これらの目的で低精度の浮動小数点データ型を使用すると、精度に関連したアーティファクトを発生させる可能性があります。例えばテクスチャー座標の場合、half には大きなテクスチャの 1 テクセルオフセットを正確に表現するのに十分な精度がありません。

中精度: half

これは中精度浮動小数点データ型です。half 値をサポートするプラットフォームでは、通常 16 ビットです。その他のプラットフォームでは float になります。

half 値は、float 値よりも範囲が狭く精度が低くなります。

半精度は、短いベクトル、方向、オブジェクト空間の位置、ハイダイナミックレンジ (HDR) の色など、高精度を必要としない値のシェーダー性能を向上させるのに便利です。

浮動小数点数

Unity のシェーダーコンパイラーは、HLSL の浮動小数点数のサフィックス を無視します。そのため、浮動小数点数のサフィックスはすべて float になります。

このコードは、Unity でサフィックス h の数字が悪影響を及ぼす可能性を示しています。 half3 packedNormal = ...; half3 normal = packedNormal * 2.0h - 1.0h;

サフィックス h は無視されるので、シェーダーコンパイラーがこれらのステップを実行するコードを生成します。 1. 中間の normal 値を高精度で計算します (float3) 2. その中間の値を half3 に変換します。 これはシェーダーの性能を低下させます。

このコードは、計算に half 値しか使わないので、より効率的です。 half3 packedNormal = ...; half3 normal = packedNormal * half(2.0) - half(1.0);

整数データ型

整数 (int データ型) はしばしばループカウンターや配列のインデックスとして使用されます。そのため、通常は、さまざまなプラットフォームで問題なく使用できます。

Depending on the platform you’ve chosen, your GPU might not support integer types.

Direct3D 11、OpenGL ES 3、Metal やその他の現段階で使用されている多くのプラットフォームでは、整数のデータ型は適切にサポートされています。そのため、ビットシフトやビットマスクを使用しても、想定通り作動します。

合成のベクトル/行列の型

HLSL には、基本の型から作成されたビルトインのベクトル型と行列型があります。例えば、float3 は .x、.y、.z コンポーネントを含む 3D ベクトルです。また、half4 は、中精度の 4D ベクトル (.x、.y、.z、.w コンポーネントを含む) です。あるいは、カラーを使用するときに有用な .r、.g、.b、.a コンポーネントを使用して、ベクトルをインデックス化することができます。

float4 myColor = ...
float redValue = myColor.r;

Matrix types are built in a similar way; for example float4x4 is a 4x4 transformation matrix. However, some platforms only support square matrices.

テクスチャ/サンプラーの型

多くの場合、HLSL コードではテクスチャを以下のように宣言します。

sampler2D _MainTex;
samplerCUBE _Cubemap;

モバイルプラットフォームでは、これらは “低精度サンプラー” に変換されます。つまり、テクスチャには低精度のデータが含まれます。 Unity プロジェクト全体のデフォルトのサンプラー精度は、Player Settings の Shader precision model ドロップダウンで変更することができます。 テクスチャに HDR カラーが含まれることが分かっている場合は、半精度サンプラーを使用するとよいでしょう。

sampler2D_half _MainTex;
samplerCUBE_half _Cubemap;

または、テクスチャがフルの float 精度のデータの 深度テクスチャ、最高精度のサンプラーを使用します。

sampler2D_float _MainTex;
samplerCUBE_float _Cubemap;

精度、ハードウェアのサポート、パフォーマンス

GPUs in desktop platforms and most modern mobile platforms support 32-bit floating point precision in the vertex and fragment shader stages. However, mobile GPUs perform better and are more energy efficient if you use lower precision.

If the platform supports lower precision, using half has the following effects:

  • Shaders use less memory, bandwidth, and power.
  • Calculations are faster. Using fewer bits can improve how the GPU allocates registers, and allow the GPU to use specialized fast execution units.

You should start with lower precision for everything except world space coordinates and texture coordinates. Check whether using lower precision causes visible errors in shader calculations (for example, color bands, or geometry that jumps between positions). If you see errors, increase precision.

無限、NaN、他の特別な浮動小数点値の適用

特殊な浮動小数点値のサポートは、実行している GPU ファミリー (主にモバイル) によって異なる場合があります。

Direct3D 10 をサポートするすべての PC の GPU は、明確に指定された IEEE 754 浮動小数点規格をサポートします。つまり、浮動小数点数は、CPU 上の通常のプログラミング言語の場合とまったく同じように動作します。

モバイル GPU のサポートレベルは、わずかに異なります。例えば、ゼロをゼロで除算すると NaN (“数字ではない”) になるモバイルがありますが、無限大、ゼロ、または、その他の特定できない値になるものもあります。ターゲットデバイスでシェーダーをテストして、それらのサポートを確認してください。

外部 GPU ドキュメント

GPU には、そのパフォーマンスや能力に関してベンダーによる詳しいガイドがあります。詳細は、それらを参照してください。

その他の参考資料

ビルトインのシェーダー変数
サンプラー状態の利用