シェーダーでテクスチャをサンプリングする場合、大抵、テクスチャのサンプリング状態は、テクスチャ設定 に基づいています。基本的に、テクスチャとサンプラーは関連付けられています。これは、DX9 スタイルのシェーダー構文を使用する場合のデフォルトの動作です。
sampler2D _MainTex;
// ...
half4 color = tex2D(_MainTex, uv);
sampler2D、sampler3D、samplerCUBE HLSL キーワードは、テクスチャとサンプラーの両方を宣言します。
ほとんどの場合はこれで用が済みます。古いグラフィックス API (OpenGL ES) で唯一サポートされている選択肢です。
多くのグラフィックス API と GPU では、テクスチャよりもサンプラーの数を減らすことができます。さらに、テクスチャとサンプラーを組み合わせた構文では、複雑なシェーダーを記述できない場合があります。例えば、Direct3D 11 では、1 つのシェーダーで最大 128 のテクスチャを使用できますが、サンプラーは最大 16 しか使用できません。
Unity では、DX11 形式の HLSL 構文のテクスチャとサンプラーを組み合わせる特別な命名規則を使用して、テクスチャとサンプラーを宣言することができます。“sampler” + TextureName という形式の名を持つサンプラーは、そのテクスチャからサンプリング状態を取得します。
上で述べたシェーダースニペットは、DX11 形式の HLSL 構文で書き直すことができ、同じことを行います。
Texture2D _MainTex;
SamplerState sampler_MainTex; // "sampler" + “_MainTex”
// ...
half4 color = _MainTex.Sample(sampler_MainTex, uv);
ただし、以下のようにすると、複数のテクスチャをサンプリングしながら、他のテクスチャのサンプラーを “再利用” するようにシェーダーを記述できます。以下の例では、3 つのテクスチャをサンプリングするために 1 つのサンプラーしか使用していません。
Texture2D _MainTex;
Texture2D _SecondTex;
Texture2D _ThirdTex;
SamplerState sampler_MainTex; // "sampler" + “_MainTex”
// ...
half4 color = _MainTex.Sample(sampler_MainTex, uv);
color += _SecondTex.Sample(sampler_MainTex, uv);
color += _ThirdTex.Sample(sampler_MainTex, uv);
Unity は、この “サンプラーを分ける” アプローチを使用して、テクスチャの宣言とサンプリングを支援するシェーダーマクロをいくつか提供しています。詳細は、ビルトインマクロ を参照してください。ビルトインマクロを使うと、上の例を以下のように書き直すことができます。
UNITY_DECLARE_TEX2D(_MainTex);
UNITY_DECLARE_TEX2D_NOSAMPLER(_SecondTex);
UNITY_DECLARE_TEX2D_NOSAMPLER(_ThirdTex);
// ...
half4 color = UNITY_SAMPLE_TEX2D(_MainTex, uv);
color += UNITY_SAMPLE_TEX2D_SAMPLER(_SecondTex, _MainTex, uv);
color += UNITY_SAMPLE_TEX2D_SAMPLER(_ThirdTex, _MainTex, uv);
上のコードは Unity がサポートするすべてのプラットフォームでコンパイルできますが、DX9 のような古いプラットフォームでは 3 つのサンプラーを使用する方法で代替されます。
“sampler” + TextureName という名前の HLSL SamplerState オブジェクトを認識することに加えて、Unity はサンプラー名の他のパターンもいくつか認識します。これは、単純なハードコーディングされたサンプリング状態をシェーダーで直接宣言するのに便利です。例:
Texture2D _MainTex;
SamplerState my_point_clamp_sampler;
// ...
half4 color = _MainTex.Sample(my_point_clamp_sampler, uv);
“my_point_clamp_sampler” という名前は、Point (最も近い) テクスチャフィルタリングと、Clamp テクスチャラップモードを使用するサンプラーとして認識されます。
インラインのサンプラー状態として認識されるサンプラー名 (大文字と小文字は区別しません)
“Point”、“Linear”、“Trilinear” は、テクスチャフィルタリングモードを設定します (必須) 。
“Clamp”、“Repeat”、“Mirror”、“MirrorOnce” は、テクスチャラップモードを設定します (必須)。
“Compare” は深度比較のためにサンプラーを設定します (任意)。HLSL SamplerComparisonState 型と SampleCmp/SampleCmpLevelZero 関数で使用します。
“AnisoX” (Xは 2/4/8/16、例えば Aniso8) を追加して、異方性フィルタリングを要求することができます。
以下は、sampler_linear_repeat と sampler_point_repeat の SamplerState でそれぞれテクスチャをサンプリングした例で、名前がフィルタリングモードをどのように制御するかを示しています。
以下は、SmpClampPoint、SmpRepeatPoint、SmpMirrorPoint、SmpMirrorOncePoint、Smp_ClampU_RepeatV_Point の各 SamplerState の例で、名前がラッピングモードをどのように制御するかを示しています。最後の例では、水平軸 (U) と垂直軸 (V) で異なるラップモードを設定しています。いずれの場合も、テクスチャ座標は –2.0 から +2.0 までです。
独立したテクスチャ + サンプラーの構文のように、インラインサンプラーの状態は一部のプラットフォームではサポートされていません。現在、インラインサンプラーは Direct3D 11/12 と Metal で実装されています。
“MirrorOnce” テクスチャラッピングモードは、ほとんどのモバイル GPU/API でサポートされていません。そのため、サポートされない場合は Mirror モードにフォールバックされます。
“AnisoX” フィルタリングモードは、プラットフォームの機能と選択した API に基づくベストエフォートであることに注意してください。実際の値は、サポートされている最大の異方性のレベルに基づいて固定されます (異方性フィルタリングがサポートされていない場合は無効になります)。
| マクロ | 用途 |
|---|---|
UNITY_DECLARE_TEX2D(name) |
テクスチャとサンプラーのペアを宣言します。 |
UNITY_DECLARE_TEX2D_NOSAMPLER(name) |
サンプラーなしでテクスチャを宣言します。 |
UNITY_DECLARE_TEX2DARRAY(name) |
テクスチャ配列のサンプラー変数を宣言します。 |
UNITY_SAMPLE_TEX2D(name,uv) |
指定されたテクスチャ座標を使用してテクスチャとサンプラーのペアからサンプリングします。 |
UNITY_SAMPLE_TEX2D_SAMPLER( name,samplername,uv) |
別のテクスチャ (samplername) からサンプラーを使用してテクスチャ (name) からサンプリングします。 |
UNITY_SAMPLE_TEX2DARRAY(name,uv) |
float3 UV のテクスチャ配列からサンプリングします。座標の z コンポーネントは配列のインデックスです。 |
UNITY_SAMPLE_TEX2DARRAY_LOD(name,uv,lod) |
明白なミップマップレベルが設定されたテクスチャ配列からサンプリングします。 |