Quad Tessellation Shaderをつくる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3896714/f864b863-046b-4809-040d-47459cb381fb.png)
これをします。

fbxのimport設定でKeepQuadsにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3896714/311263e1-c759-8705-c8b0-93f8b2e9e938.png)

hullShaderとDomainShaderを使ってquadテセレーションをするために。
あとはhullConstantで割る量を調整して、domainをquadにします。
```hlsl
Shader "Unlit/quadTess"
{
    Properties
    {
        _OuterTess ("Outer Tess", Range(1, 64)) = 2
        _InnerTess ("Inner Tess", Range(1, 64)) = 2 
    }
    SubShader
    {
        // disable batching to avoid dynamic batching issues
        Tags { "RenderType"="Opaque" "DisableBatching"="True" }
        LOD 100
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma hull hullShader
            #pragma domain domainShader
            #pragma target 5.0

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2h
            {
                float4 vertex : POS;
            };
            struct h2d
            {
                float4 vertex : POS;
            };
            struct constantOutput
            {
                float edges[4] : SV_TessFactor;
                float inside[2] : SV_InsideTessFactor;
            };
            struct d2f
            {
                float4 vertex : SV_POSITION;
            };
            v2h vert (appdata v)
            {
                v2h o;
                o.vertex = v.vertex;
                return o;
            }
            #define INPUT_PATCH_SIZE 4
            #define OUTPUT_PATCH_SIZE 4
            float _InnerTess;
            float _OuterTess;
            constantOutput hullConstant (InputPatch<v2h, INPUT_PATCH_SIZE> i)
            {
                constantOutput output;
                output.edges[0] = output.edges[1] = output.edges[2] = output.edges[3] = _OuterTess;
                output.inside[0] = output.inside[1] = _InnerTess;
                return output;
            }
            [domain("quad")]
            [partitioning("integer")]
            [outputtopology("triangle_cw")]
	        [outputcontrolpoints(4)]
	        [patchconstantfunc("hullConstant")]
            h2d hullShader (InputPatch<v2h, INPUT_PATCH_SIZE> i, uint id:SV_OutputControlPointID)
            {
                h2d o; 
                o.vertex = i[id].vertex;
                return o;
            }
             
            [domain("quad")]
            d2f domainShader (constantOutput output, const OutputPatch<h2d,OUTPUT_PATCH_SIZE> i, float2 uv : SV_DomainLocation) 
            {
                d2f o;
                float3 pos = lerp(lerp(i[0].vertex, i[1].vertex, uv.x),lerp(i[3].vertex, i[2].vertex, uv.x), uv.y);
                o.vertex = UnityObjectToClipPos(float4(pos,1));
                return o;
            }
            
            fixed4 frag (d2f i) : SV_Target
            {
                fixed4 col = float4((1).xxxx);
                return col;
            }
            ENDCG
        }
    }
}


```

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3896714/79e50ecd-623b-56b8-ea93-5d96d4bc908e.png">

ドメインシェーダーのSV_DomainLocationがこうなってるので、以下のようにLerpで位置を指定してます。
```hlsl
float3 pos = lerp(lerp(i[0].vertex, i[1].vertex, uv.x),lerp(i[3].vertex, i[2].vertex, uv.x), uv.y);
```

Batchingを使用するとメッシュが三角面として解釈される(憶測)ので、
"DisableBatching"="True とすることで、ちょっとした問題を解決できます。
さらに、VRChatではDynamic Batchingがデフォルトでオンの為、Static Batchingをオフにするだけでは解決されません。
上のシェーダーは四面用の為、三角面の場合、存在しない4つ目の頂点を求めてワールド原点に頂点が飛びます。
(この辺曖昧なので有識者教えてください)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3896714/785d29df-dae1-390d-8bc7-c6abfca2723c.png)
良い感じ。

# 参考

https://www.reedbeta.com/blog/tess-quick-ref/