215 lines
9.0 KiB
Plaintext
215 lines
9.0 KiB
Plaintext
|
|
struct OutputPatchConstant
|
|
{
|
|
float edge[3] : SV_TessFactor;
|
|
float inside : SV_InsideTessFactor;
|
|
};
|
|
|
|
|
|
#if defined(SHADER_API_XBOXONE) || defined(SHADER_API_PSSL)
|
|
// AMD recommand this value for GCN http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/05/GCNPerformanceTweets.pdf
|
|
#define MAX_TESSELLATION_FACTORS 15.0
|
|
#else
|
|
#define MAX_TESSELLATION_FACTORS 64.0
|
|
#endif
|
|
|
|
float CalcDistanceTessFactor (float3 wpos, float minDist, float maxDist, float tess, float3 camPos)
|
|
{
|
|
float dist = distance (wpos, camPos);
|
|
float f = clamp(1.0 - (dist - minDist) / (maxDist - minDist), 0.01, 1.0) * tess;
|
|
return f;
|
|
}
|
|
|
|
float4 CalcTriEdgeTessFactors (float3 triVertexFactors)
|
|
{
|
|
float4 tess;
|
|
tess.x = 0.5 * (triVertexFactors.y + triVertexFactors.z);
|
|
tess.y = 0.5 * (triVertexFactors.x + triVertexFactors.z);
|
|
tess.z = 0.5 * (triVertexFactors.x + triVertexFactors.y);
|
|
tess.w = (triVertexFactors.x + triVertexFactors.y + triVertexFactors.z) / 3.0f;
|
|
return tess;
|
|
}
|
|
|
|
|
|
float4 DistanceBasedTess (float3 v0, float3 v1, float3 v2, float minDist, float maxDist, float tess)
|
|
{
|
|
float3 f;
|
|
|
|
float3 camPos = TransformWorldToObject(GetCameraWorldPosition());
|
|
f.x = CalcDistanceTessFactor (v0,minDist,maxDist,tess, camPos);
|
|
f.y = CalcDistanceTessFactor (v1,minDist,maxDist,tess, camPos);
|
|
f.z = CalcDistanceTessFactor (v2,minDist,maxDist,tess, camPos);
|
|
|
|
return CalcTriEdgeTessFactors (f);
|
|
}
|
|
|
|
#if _TESSEDGE || _TESSPHONG
|
|
float CalcEdgeTessFactor (float3 wpos0, float3 wpos1, float edgeLen)
|
|
{
|
|
float3 camPos = TransformWorldToObject(GetCameraWorldPosition());
|
|
// distance to edge center
|
|
float dist = distance (0.5 * (wpos0+wpos1), GetCameraWorldPosition());
|
|
// length of the edge
|
|
float len = distance(wpos0, wpos1);
|
|
// edgeLen is approximate desired size in pixels
|
|
float f = max(len * _ScreenParams.y / (edgeLen * dist), 1.0);
|
|
return f;
|
|
}
|
|
|
|
float TessDistanceFromPlane (float3 pos, float4 plane)
|
|
{
|
|
float d = dot (float4(pos,1.0f), plane);
|
|
return d;
|
|
}
|
|
|
|
|
|
|
|
float4 EdgeLengthBasedTessCull (float4 v0, float4 v1, float4 v2, float edgeLength)
|
|
{
|
|
float3 pos0 = mul(unity_ObjectToWorld,v0).xyz;
|
|
float3 pos1 = mul(unity_ObjectToWorld,v1).xyz;
|
|
float3 pos2 = mul(unity_ObjectToWorld,v2).xyz;
|
|
float4 tess;
|
|
tess.x = CalcEdgeTessFactor (pos1, pos2, edgeLength);
|
|
tess.y = CalcEdgeTessFactor (pos2, pos0, edgeLength);
|
|
tess.z = CalcEdgeTessFactor (pos0, pos1, edgeLength);
|
|
tess.w = (tess.x + tess.y + tess.z) / 3.0f;
|
|
return tess;
|
|
}
|
|
#endif
|
|
|
|
float4 Tessellation (TessVertex v0, TessVertex v1, TessVertex v2)
|
|
{
|
|
float3 fac = GetTessFactors();
|
|
#if _TESSEDGE
|
|
return EdgeLengthBasedTessCull(v0.vertex, v1.vertex, v2.vertex, fac.y);
|
|
#else
|
|
return DistanceBasedTess(v0.vertex.xyz, v1.vertex.xyz, v2.vertex.xyz, fac.x, fac.y, fac.z);
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
OutputPatchConstant Hullconst (InputPatch<TessVertex,3> v)
|
|
{
|
|
OutputPatchConstant o = (OutputPatchConstant)0;
|
|
float4 tf = Tessellation( v[0], v[1], v[2] );
|
|
tf = min(tf, MAX_TESSELLATION_FACTORS);
|
|
o.edge[0] = tf.x;
|
|
o.edge[1] = tf.y;
|
|
o.edge[2] = tf.z;
|
|
o.inside = tf.w;
|
|
return o;
|
|
}
|
|
|
|
[maxtessfactor(MAX_TESSELLATION_FACTORS)]
|
|
[domain("tri")]
|
|
[partitioning("fractional_odd")]
|
|
[outputtopology("triangle_cw")]
|
|
[patchconstantfunc("Hullconst")]
|
|
[outputcontrolpoints(3)]
|
|
TessVertex Hull (InputPatch<TessVertex,3> v, uint id : SV_OutputControlPointID)
|
|
{
|
|
return v[id];
|
|
}
|
|
|
|
|
|
TessVertex TessVert(VertexData i)
|
|
{
|
|
TessVertex o = (TessVertex)o;
|
|
UNITY_SETUP_INSTANCE_ID(i);
|
|
UNITY_TRANSFER_INSTANCE_ID(i, o);
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
|
|
|
VertexToPixel v2p = (VertexToPixel)0;
|
|
|
|
ChainModifyVertex(i, v2p);
|
|
|
|
|
|
o.vertex = i.vertex;
|
|
o.normal = i.normal;
|
|
|
|
o.texcoord0 = i.texcoord0;
|
|
#if !_MICROTERRAIN || _TERRAINBLENDABLESHADER
|
|
o.tangent = i.tangent;
|
|
o.texcoord1 = i.texcoord1;
|
|
o.texcoord2 = i.texcoord2;
|
|
#endif
|
|
%UV3% o.texcoord3 = i.texcoord3;
|
|
%VERTEXCOLOR% o.vertexColor = i.vertexColor;
|
|
|
|
%EXTRAV2F0% o.extraV2F0 = v2p.extraV2F0;
|
|
%EXTRAV2F1% o.extraV2F1 = v2p.extraV2F1;
|
|
%EXTRAV2F2% o.extraV2F2 = v2p.extraV2F2;
|
|
%EXTRAV2F3% o.extraV2F3 = v2p.extraV2F3;
|
|
%EXTRAV2F4% o.extraV2F4 = v2p.extraV2F4;
|
|
%EXTRAV2F5% o.extraV2F5 = v2p.extraV2F5;
|
|
%EXTRAV2F6% o.extraV2F6 = v2p.extraV2F6;
|
|
%EXTRAV2F7% o.extraV2F7 = v2p.extraV2F7;
|
|
|
|
#if _HDRP && (_PASSMOTIONVECTOR || (_PASSFORWARD && defined(_WRITE_TRANSPARENT_MOTION_VECTOR)))
|
|
o.previousPositionOS = i.previousPositionOS;
|
|
#if defined (_ADD_PRECOMPUTED_VELOCITY)
|
|
o.precomputedVelocity = i.precomputedVelocity;
|
|
#endif
|
|
#endif
|
|
|
|
return o;
|
|
}
|
|
|
|
|
|
[domain("tri")]
|
|
VertexToPixel Domain (OutputPatchConstant tessFactors, const OutputPatch<TessVertex,3> vi, float3 bary : SV_DomainLocation)
|
|
{
|
|
precise VertexData v = (VertexData)0;
|
|
UNITY_TRANSFER_INSTANCE_ID(vi[0], v);
|
|
|
|
v.vertex = vi[0].vertex * bary.x + vi[1].vertex * bary.y + vi[2].vertex * bary.z;
|
|
v.normal = vi[0].normal * bary.x + vi[1].normal * bary.y + vi[2].normal * bary.z;
|
|
v.texcoord0 = vi[0].texcoord0 * bary.x + vi[1].texcoord0 * bary.y + vi[2].texcoord0 * bary.z;
|
|
#if !_MICROTERRAIN || _TERRAINBLENDABLESHADER
|
|
v.tangent = vi[0].tangent * bary.x + vi[1].tangent * bary.y + vi[2].tangent * bary.z;
|
|
v.texcoord1 = vi[0].texcoord1 * bary.x + vi[1].texcoord1 * bary.y + vi[2].texcoord1 * bary.z;
|
|
v.texcoord2 = vi[0].texcoord2 * bary.x + vi[1].texcoord2 * bary.y + vi[2].texcoord2 * bary.z;
|
|
#endif
|
|
%UV3% v.texcoord3 = vi[0].texcoord3 * bary.x + vi[1].texcoord3 * bary.y + vi[2].texcoord3 * bary.z;
|
|
%VERTEXCOLOR% v.vertexColor = vi[0].vertexColor * bary.x + vi[1].vertexColor * bary.y + vi[2].vertexColor * bary.z;
|
|
|
|
#if _HDRP && (_PASSMOTIONVECTOR || (_PASSFORWARD && defined(_WRITE_TRANSPARENT_MOTION_VECTOR)))
|
|
v.previousPositionOS = vi[0].previousPositionOS * bary.x + vi[1].previousPositionOS * bary.y + vi[2].previousPositionOS * bary.z;
|
|
#if defined (_ADD_PRECOMPUTED_VELOCITY)
|
|
v.precomputedVelocity = vi[0].precomputedVelocity * bary.x + vi[1].precomputedVelocity * bary.y + vi[2].precomputedVelocity * bary.z;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
VertexToPixel d = (VertexToPixel)0;
|
|
%EXTRAV2F0% d.extraV2F0 = vi[0].extraV2F0 * bary.x + vi[1].extraV2F0 * bary.y + vi[2].extraV2F0 * bary.z;
|
|
%EXTRAV2F1% d.extraV2F1 = vi[0].extraV2F1 * bary.x + vi[1].extraV2F1 * bary.y + vi[2].extraV2F1 * bary.z;
|
|
%EXTRAV2F2% d.extraV2F2 = vi[0].extraV2F2 * bary.x + vi[1].extraV2F2 * bary.y + vi[2].extraV2F2 * bary.z;
|
|
%EXTRAV2F3% d.extraV2F3 = vi[0].extraV2F3 * bary.x + vi[1].extraV2F3 * bary.y + vi[2].extraV2F3 * bary.z;
|
|
%EXTRAV2F4% d.extraV2F4 = vi[0].extraV2F4 * bary.x + vi[1].extraV2F4 * bary.y + vi[2].extraV2F4 * bary.z;
|
|
%EXTRAV2F5% d.extraV2F5 = vi[0].extraV2F5 * bary.x + vi[1].extraV2F5 * bary.y + vi[2].extraV2F5 * bary.z;
|
|
%EXTRAV2F6% d.extraV2F6 = vi[0].extraV2F6 * bary.x + vi[1].extraV2F6 * bary.y + vi[2].extraV2F6 * bary.z;
|
|
%EXTRAV2F7% d.extraV2F7 = vi[0].extraV2F7 * bary.x + vi[1].extraV2F7 * bary.y + vi[2].extraV2F7 * bary.z;
|
|
|
|
ChainModifyTessellatedVertex(v, d);
|
|
|
|
VertexToPixel v2p = Vert(v);
|
|
|
|
%EXTRAV2F0% v2p.extraV2F0 = d.extraV2F0;
|
|
%EXTRAV2F1% v2p.extraV2F1 = d.extraV2F1;
|
|
%EXTRAV2F2% v2p.extraV2F2 = d.extraV2F2;
|
|
%EXTRAV2F3% v2p.extraV2F3 = d.extraV2F3;
|
|
%EXTRAV2F4% v2p.extraV2F0 = d.extraV2F4;
|
|
%EXTRAV2F5% v2p.extraV2F1 = d.extraV2F5;
|
|
%EXTRAV2F6% v2p.extraV2F2 = d.extraV2F6;
|
|
%EXTRAV2F7% v2p.extraV2F3 = d.extraV2F7;
|
|
|
|
UNITY_TRANSFER_INSTANCE_ID(vi[0], v2p);
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(v2p);
|
|
|
|
return v2p;
|
|
}
|