0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Quad Tessellation Shaderをつくる

Last updated at Posted at 2024-09-27

image.png
これをします。

fbxのimport設定でKeepQuadsにします。
image.png

hullShaderとDomainShaderを使ってquadテセレーションをするために。
あとはhullConstantで割る量を調整して、domainをquadにします。

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
        }
    }
}


ドメインシェーダーのSV_DomainLocationがこうなってるので、以下のようにLerpで位置を指定してます。

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
良い感じ。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?