【Unity】テクスチャ情報から頂点イジるシェーダーを作ってみる【頂点テクスチャフェッチ（VTF）】

テクスチャを読み込んで、頂点座標をイジるシンプルなシェーダーのサンプルを作ってみました！

テクスチャ情報から頂点を制御したい！と考えている方の参考になあれば幸いです。

## 頂点テクスチャフェッチ（VTF）とは？
VTFについて、丁寧にまとめられていた記事がありましたので引用します。
>頂点テクスチャフェッチは、その英語表記の頭文字を取って VTF などと呼ばれることもあります。近年のコンシューマゲームなどでも割と活躍している技術の一つで、その応用範囲はかなり広いと言っていいと思います。

>頂点テクスチャフェッチとは、簡潔に言うなら[ 頂点シェーダ内でテクスチャを参照すること ]を指します。
[頂点テクスチャフェッチ(VTF](https://wgld.org/d/webgl/w071.html)

早速、サンプルを紹介します！

## シェーダーの完成形
ご紹介するサンプルは貼り付けたテクスチャのRGBの”R”値によって、y座標の頂点が変わるシェーダーになります。
<img width="532" alt="スクリーンショット 2019-02-19 22.56.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/314351/4bd3ad17-728f-020c-7ecb-bd1726d4fba1.png">

上図はわかりやすく白黒のテクスチャを貼り付けたオブジェクトです。白い部分が盛り上がっているのを、ご確認いただけると思います。

## ソース
ソースは以下の通りです。

```vtfSample.shader
Shader "Unlit/vtfSample"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Tex2Dlod ("Tex2DlodSample", 2D) = "white" {}
        
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100
        Cull off

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float2 texcoord : TEXCOORD1;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float2 texcoord : TEXCOORD1;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            sampler2D _Tex2Dlod;
            float4    _Tex2Dlod_ST;

            v2f vert (appdata v)
            {
                v2f o;
                                
                float d = tex2Dlod(_Tex2Dlod, float4(v.texcoord.xy,0,0)).r;
                v.vertex.y += d;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

```

Unityにて、頂点シェーダーで参照したいテクスチャを`Tex2DlodSample`にアタッチ、フラグメントシェーダーで参照したいテクスチャを`Texture`にアタッチすればOKです。

頂点シェーダーでテクスチャを読み込みときは、`tex2Dlod`を使いますのでご注意ください！

### 注意点：テクスチャの設定でWrap ModeをClampにしよう！
ただ、このままですと、こんな風に崩れてしまう可能性があります。
![cu31WJvQ.jpg](https://qiita-image-store.s3.amazonaws.com/0/314351/0c87479b-9e5c-7028-f956-6337cfc3e2fa.jpeg)

原因はテクスチャのWrap ModeがRepeatになっているため、端っこが白黒になってしまっているからです。

テクスチャのWrap ModeをClampにすれば万事解決です！
<img width="416" alt="スクリーンショット_2019-02-20_17_50_46.png" src="https://qiita-image-store.s3.amazonaws.com/0/314351/2bb88a3e-b86d-ba9d-13ed-f3631a0437f8.png">

##　最後に
いかがだったでしょうか？

今回は超シンプルなシェーダーになっていますが、ここから様々な表現ができると思います。

ぜひ色々いじってみてください！

## スペシャルサンクス
このシェーダー作るのに、うまくいかなくて悪戦苦闘していたのですが、[伊藤さん@warapuri](https://twitter.com/warapuri)に質問したところ、無事に解決できました。

この場をかりて感謝御礼申し上げますm(_ _)m

## 参考記事
- [UnityTexturePaintでリアルタイムにオブジェクトを変形する](http://esprog.hatenablog.com/entry/2016/10/17/202513)
- [UnityのシェーダーでVTF(vertex texture fetch)](http://yamayatakeshi.jp/unity%E3%81%AE%E3%82%B7%E3%82%A7%E3%83%BC%E3%83%80%E3%83%BC%E3%81%A7vtfvertex-texture-fetch/)