シェーダーのデータ型と精度
ShaderLab シンタックス

サンプラー状態の利用

テクスチャとサンプラーを組み合わせる

シェーダーでテクスチャをサンプリングするほとんどの場合、テクスチャサンプリングの状態は テクスチャ設定 に基づきます。基本的に、テクスチャとサンプラーは組み合わせて使用されます。これは、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);

一部の古いプラットフォーム (例えば OpenGL ES 2.0) では、DX11 形式の HLSL 構文は使用できないことに気を付けてください。詳しくは シェーダー言語 を参照してください。#pragma target 3.5 (シェーダーコンパイルターゲット を参照) を指定して、古いプラットフォームでシェーダーを使用しないようにすることができます。

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 サンプラー状態のオブジェクトを認識することに加えて、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” は、テクスチャラップモードを設定します (必須)。

    • ラップモードは 軸 (UVW) ごとに指定できます。例えば “ClampU_RepeatV”
  • “Compare” は深度比較のためにサンプラーを設定します (任意)。HLSL SamplerComparisonState 型と SampleCmp/SampleCmpLevelZero 関数で使用します。

以下は、それぞれ sampler_linear_repeatsampler_point_repeat のサンプラー状態でテクスチャをサンプリングした例です。名前によってどのようにフィルタリングモードが制御されるかを示しています。

以下は、それぞれ SmpClampPointSmpRepeatPointSmpMirrorPointSmpMirrorOncePointSmp_ClampU_RepeatV_Point SamplerStates の例です。名前がラッピングモードを制御する方法を示しています。最後の例では、水平軸 (U) と垂直軸 (V) に異なるラップモードが設定されています。すべての例のテクスチャ座標は –2.0 から +2.0 の範囲です。

独立したテクスチャ + サンプラーの構文のように、インラインサンプラーの状態は一部のプラットフォームではサポートされていません。現在、インラインサンプラーは Direct3D 11/12、PS4、XboxOne、Metal で実装されています。

“MirrorOnce” テクスチャラッピングモードは、ほとんどのモバイル GPU/API でサポートされていません。そのため、サポートされない場合は Mirror モードに代替されます。


シェーダーのデータ型と精度
ShaderLab シンタックス