Unity Custom Shader 記述におけるテクスチャの扱い (URP 環境)
Unity シェーダーの勉強.
テクスチャ周りについて覚え書き.
頂点シェーダー, フラグメントシェーダーについての基礎は 過去の記事 を参照のこと.
検証環境
- Windows 11 Home
- Unity 6000.0.50f1
- Universal Render Pipline
テクスチャの宣言回り
テクスチャを各種シェーダー内で使用するには
- プロパティブロックにおける
_BaseMap
の宣言 - 各種構造体における uv 変数の宣言
_BaseMap
とサンプラーの宣言
が必要となる
プロパティブロックにおける _BaseMap
の宣言
_BaseMap
を以下のように宣言する
Properties { [MainTexture] _BaseMap("Base Map", 2D) = "white" }
"white"
はテクスチャが設定されていない場合におけるデフォルトの色を指定している- この Property を設定することでエディターからテクスチャをセットできるようになる
各種構造体における uv 変数の宣言
- 頂点シェーダーとフラグメントシェーダーで uv 座標を扱うために以下のように構造体を定義
struct Attributes { // vertices position of object space float4 positionOS : POSITION; // uv position float2 uv : TEXCOORD0; }; struct Varyings { // vertices position of screen space float4 positionHCS : SV_POSITION; // uv position float2 uv : TEXCOORD0; };
_BaseMap
とサンプラーの宣言
- HLSLPROGRAM 内でテクスチャを扱うために以下のように宣言
// declear basemap TEXTURE2D(_BaseMap); // declear sampler SAMPLER(sampler_BaseMap); // basemap for frag CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; CBUFFER_END
- サンプラーの役割などは後述
タイリングやオフセットの処理
- 頂点シェーダーに以下を記述することでタイリング (テクスチャの繰り返し表示) とオフセット (ずらし) の処理を行う
// set uv position OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap);
- Stack Overflow の記事 によると
TRANSFORM_TEX
のマクロは以下のように定義されるらしい
// Transforms 2D UV by scale/bias property #define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
- ここで
name##_ST
の xy はタイリング, zw はオフセットを表す
サンプリングについて
SAMPLE_TEXTURE2D
関数はテクスチャに対してサンプリングを行い指定された UV 座標における色を返す
half4 color = SAMPLE_TEXTURE2D(texture, sampler, uv);
- sampler において補完方法の選択などが行える
オブジェクトへの適用
- オブジェクトに適用するとテクスチャが表示される (タイリング 10x10, offset 0 で適用)

- シェーダーのサンプルコードは以下の通り
Shader "TextureTile/URPUnlitShaderBasic" { Properties { [MainTexture] _BaseMap("Base Map", 2D) = "white" } SubShader { Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" } Pass { HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct Attributes { // vertices position of object space float4 positionOS : POSITION; // uv position float2 uv : TEXCOORD0; }; struct Varyings { // vertices position of screen space float4 positionHCS : SV_POSITION; // uv position float2 uv : TEXCOORD0; }; // declear basemap TEXTURE2D(_BaseMap); // declear sampler SAMPLER(sampler_BaseMap); // basemap for frag CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; CBUFFER_END // vertex shader Varyings vert(Attributes IN) { // output object Varyings OUT; // position change with noise float3 outPos = IN.positionOS.xyz; // to clip space OUT.positionHCS = TransformObjectToHClip(outPos); // set uv position OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap); return OUT; } // fragment shader half4 frag(Varyings IN) : SV_Target { // sampling texture and get color half4 textureColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv); return textureColor; } ENDHLSL } } }
(おまけ) テクスチャを時間とともに動かす
- 各頂点がテクスチャ上のどの位置にいるかは頂点シェーダーから操作可能であるため, 以下のようにすれば時間とともにテクスチャが動くマテリアルが作成可能
// set uv position float2 outUv = TRANSFORM_TEX(IN.uv, _BaseMap); float speed = 10.0; outUv.x += _Time.x * speed; outUv.y += _Time.x * speed; OUT.uv = outUv;
上記コードではセットするテクスチャの Wrap Mode について repeat になっているか確認が必要 (uv の各座標の値が 0-1 の範囲を超えるため)
オブジェクトに適用した結果は以下の通り