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つ目の頂点を求めてワールド原点に頂点が飛びます。
(この辺曖昧なので有識者教えてください)
参考