Unityでインラインサンプラーステートを使ってテクスチャのWrap ModeやFilter Modeをシェーダで指定する方法についてまとめました。
Unity2020.3.15f2
サンプラーステートをシェーダで指定する
サンプラーステートとは、テクスチャのラッピングモードやフィルタリングモードといった情報のことです。
基本的にはテクスチャに紐づく情報であり、Unityではテクスチャのインポート設定として設定できます。
Unityのシェーダでは、例えば以下のように記述することでこのインポート設定を使わずにサンプラーステートを直接指定することができます。
SamplerState sampler_point_clamp;
上記のサンプラはフィルタリングモードがPoint、ラッピングモードがClampに設定されます。
サンプラの設定は名前により決まります。命名ルールは以下の通りです。
命名ルール | 指定が必須か | 説明 |
---|---|---|
Point / Linear / Trilinear | YES | フィルタリングモードを指定 |
Clamp / Repeat / Mirror / MirrorOnce | YES | ラッピングモードを指定 ClampU_RepeatVのように軸ごとに指定も可能 |
AnisoX | NO | 異方性フィルタリングの値を指定 Xには2/4/8/16の数値を指定する |
Compare | NO | 深度比較のためのサンプラを設定する |
大文字小文字の区別はなく、SamplerState型の名前に上記の単語を使っていれば良いようです。
linearmirrorとかでも行けました。
またこの機能はマニュアルによると使えるプラットフォームが限られるようです。
Currently they are implemented on Direct3D 11/12, PS4, XboxOne and Metal.
ただしこのページは2017年から更新されていないのでアテにならなそうです。
実際VulkanのAndroid(Snapdragon439)でも動作確認ができました。
シェーダを書く
さてそれではインラインサンプラーステートを使ったシェーダを記述します。
※URP用のシェーダです
Shader "Example" { Properties { _BaseMap("Base Map", 2D) = "white" {} } SubShader { Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "IgnoreProjector" = "True" "Queue" = "Geometry" } Pass { HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; }; struct Varyings { float4 positionHCS : SV_POSITION; float2 uv : TEXCOORD0; }; // このマクロではサンプラは定義されないのでこれを使う TEXTURE2D(_BaseMap); // インラインサンプラーステート SamplerState sampler_point_mirror; CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; CBUFFER_END Varyings vert(Attributes IN) { Varyings OUT; OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz); OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap); return OUT; } half4 frag(Varyings IN) : SV_Target { // インラインサンプラーステートを使ったサンプリング return _BaseMap.Sample(sampler_point_mirror, IN.uv); } ENDHLSL } } }
説明はコメントに書いた通りです。
今回はフィルタリングモードをPoint、ラッピングモードをMirrorにしたサンプラを使ってみました。
結果
それでは実際にこのシェーダを使ってレンダリングしてみます。
以下のようなテクスチャを用意して、インポート設定でWrap ModeをClampにしておきます。
Tilingを2x2にして、先程のシェーダで描画すると以下の通りの結果となります。
Wrap ModeがMirrorの状態でサンプリングできていることが確認できました。