Version: 2020.3
言語: 日本語
シェーダーのデータ型と精度
Unity での GLSL

サンプラー状態の利用

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

シェーダーでテクスチャをサンプリングする場合、大抵、テクスチャのサンプリング状態は、テクスチャ設定 に基づいています。基本的に、テクスチャとサンプラーは関連付けられています。これは、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);

ただし、DX11 スタイルの HLSL シンタックスは、いくつかの古いプラット フォーム (例えば、OpenGL ES 2.0) では使用できないことに注意してください。詳細は Unity の HLSL を参照してください。#pragma target 3.5 (HLSL でシェーダーモデルと GPU 機能を特定する を参照) を指定して、シェーダーが古いプラットフォームを使用することをスキップすることもできます。

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 関数で使用します。

  • “AnisoX” (Xは 2/4/8/16、例えば Ansio8) を追加して、異方性フィルタリングを要求することができます。 以下は、sampler_linear_repeatsampler_point_repeat の SamplerState でそれぞれテクスチャをサンプリングした例で、名前がフィルタリングモードをどのように制御するかを示しています。

以下は、SmpClampPointSmpRepeatPointSmpMirrorPointSmpMirrorOncePointSmp_ClampU_RepeatV_Point の SamplerState をそれぞれ使用した例で、名前がラップモードをどのように制御するかを示しています。最後の例では、水平軸 (U) と垂直軸 (V) で異なるラップモードを設定しています。いずれの場合も、テクスチャ座標は –2.0 から +2.0 までです。

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

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


  • 2017–06–01 公開ページ

  • 2017.1 の新機能NewIn20171

シェーダーのデータ型と精度
Unity での GLSL