您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
136 行
5.8 KiB
136 行
5.8 KiB
#define TESSELLATION_INTERPOLATE_BARY(name, bary) ouput.name = input0.name * bary.x + input1.name * bary.y + input2.name * bary.z
|
|
|
|
float3 ProjectPointOnPlane(float3 position, float3 planePosition, float3 planeNormal)
|
|
{
|
|
return position - (dot(position - planePosition, planeNormal) * planeNormal);
|
|
}
|
|
|
|
// p0, p1, p2 triangle world position
|
|
// p0, p1, p2 triangle world vertex normal
|
|
float3 PhongTessellation(float3 positionWS, float3 p0, float3 p1, float3 p2, float3 n0, float3 n1, float3 n2, float3 baryCoords, float shape)
|
|
{
|
|
float3 c0 = ProjectPointOnPlane(positionWS, p0, n0);
|
|
float3 c1 = ProjectPointOnPlane(positionWS, p1, n1);
|
|
float3 c2 = ProjectPointOnPlane(positionWS, p2, n2);
|
|
|
|
float3 phongPositionWS = baryCoords.x * c0 + baryCoords.y * c1 + baryCoords.z * c2;
|
|
|
|
return lerp(positionWS, phongPositionWS, shape);
|
|
}
|
|
|
|
// ---- utility functions
|
|
float CalcDistanceTessFactor(float3 positionWS, float minDist, float maxDist, float4x4 objectToWorld, float3 cameraPosWS)
|
|
{
|
|
float dist = distance(positionWS, cameraPosWS);
|
|
float f = clamp(1.0 - (dist - minDist) / (maxDist - minDist), 0.01, 1.0);
|
|
return f;
|
|
}
|
|
|
|
float4 UnityCalcTriEdgeTessFactors(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;
|
|
}
|
|
|
|
/*
|
|
float UnityCalcEdgeTessFactor(float3 wpos0, float3 wpos1, float edgeLen)
|
|
{
|
|
// distance to edge center
|
|
float dist = distance(0.5 * (wpos0 + wpos1), _WorldSpaceCameraPos);
|
|
// 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 UnityDistanceFromPlane(float3 pos, float4 plane)
|
|
{
|
|
float d = dot(float4(pos, 1.0f), plane);
|
|
return d;
|
|
}
|
|
|
|
// Returns true if triangle with given 3 world positions is outside of camera's view frustum.
|
|
// cullEps is distance outside of frustum that is still considered to be inside (i.e. max displacement)
|
|
bool UnityWorldViewFrustumCull(float3 wpos0, float3 wpos1, float3 wpos2, float cullEps)
|
|
{
|
|
float4 planeTest;
|
|
|
|
// left
|
|
planeTest.x = ((UnityDistanceFromPlane(wpos0, unity_CameraWorldClipPlanes[0]) > -cullEps) ? 1.0f : 0.0f) +
|
|
((UnityDistanceFromPlane(wpos1, unity_CameraWorldClipPlanes[0]) > -cullEps) ? 1.0f : 0.0f) +
|
|
((UnityDistanceFromPlane(wpos2, unity_CameraWorldClipPlanes[0]) > -cullEps) ? 1.0f : 0.0f);
|
|
// right
|
|
planeTest.y = ((UnityDistanceFromPlane(wpos0, unity_CameraWorldClipPlanes[1]) > -cullEps) ? 1.0f : 0.0f) +
|
|
((UnityDistanceFromPlane(wpos1, unity_CameraWorldClipPlanes[1]) > -cullEps) ? 1.0f : 0.0f) +
|
|
((UnityDistanceFromPlane(wpos2, unity_CameraWorldClipPlanes[1]) > -cullEps) ? 1.0f : 0.0f);
|
|
// top
|
|
planeTest.z = ((UnityDistanceFromPlane(wpos0, unity_CameraWorldClipPlanes[2]) > -cullEps) ? 1.0f : 0.0f) +
|
|
((UnityDistanceFromPlane(wpos1, unity_CameraWorldClipPlanes[2]) > -cullEps) ? 1.0f : 0.0f) +
|
|
((UnityDistanceFromPlane(wpos2, unity_CameraWorldClipPlanes[2]) > -cullEps) ? 1.0f : 0.0f);
|
|
// bottom
|
|
planeTest.w = ((UnityDistanceFromPlane(wpos0, unity_CameraWorldClipPlanes[3]) > -cullEps) ? 1.0f : 0.0f) +
|
|
((UnityDistanceFromPlane(wpos1, unity_CameraWorldClipPlanes[3]) > -cullEps) ? 1.0f : 0.0f) +
|
|
((UnityDistanceFromPlane(wpos2, unity_CameraWorldClipPlanes[3]) > -cullEps) ? 1.0f : 0.0f);
|
|
|
|
// has to pass all 4 plane tests to be visible
|
|
return !all(planeTest);
|
|
}
|
|
*/
|
|
|
|
// ---- functions that compute tessellation factors
|
|
// Distance based tessellation:
|
|
// Tessellation level is "tess" before "minDist" from camera, and linearly decreases to 1
|
|
// up to "maxDist" from camera.
|
|
float4 DistanceBasedTess(float3 p0, float3 p1, float3 p2, float minDist, float maxDist, float4x4 objectToWorld, float3 cameraPosWS)
|
|
{
|
|
float3 f;
|
|
f.x = CalcDistanceTessFactor(p0, minDist, maxDist, objectToWorld, cameraPosWS);
|
|
f.y = CalcDistanceTessFactor(p1, minDist, maxDist, objectToWorld, cameraPosWS);
|
|
f.z = CalcDistanceTessFactor(p2, minDist, maxDist, objectToWorld, cameraPosWS);
|
|
return UnityCalcTriEdgeTessFactors(f);
|
|
}
|
|
|
|
/*
|
|
// Desired edge length based tessellation:
|
|
// Approximate resulting edge length in pixels is "edgeLength".
|
|
// Does not take viewing FOV into account, just flat out divides factor by distance.
|
|
float4 UnityEdgeLengthBasedTess(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 = UnityCalcEdgeTessFactor(pos1, pos2, edgeLength);
|
|
tess.y = UnityCalcEdgeTessFactor(pos2, pos0, edgeLength);
|
|
tess.z = UnityCalcEdgeTessFactor(pos0, pos1, edgeLength);
|
|
tess.w = (tess.x + tess.y + tess.z) / 3.0f;
|
|
return tess;
|
|
}
|
|
|
|
// Same as UnityEdgeLengthBasedTess, but also does patch frustum culling:
|
|
// patches outside of camera's view are culled before GPU tessellation. Saves some wasted work.
|
|
float4 UnityEdgeLengthBasedTessCull(float4 v0, float4 v1, float4 v2, float edgeLength, float maxDisplacement)
|
|
{
|
|
float3 pos0 = mul(unity_ObjectToWorld, v0).xyz;
|
|
float3 pos1 = mul(unity_ObjectToWorld, v1).xyz;
|
|
float3 pos2 = mul(unity_ObjectToWorld, v2).xyz;
|
|
float4 tess;
|
|
if (UnityWorldViewFrustumCull(pos0, pos1, pos2, maxDisplacement))
|
|
{
|
|
tess = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
tess.x = UnityCalcEdgeTessFactor(pos1, pos2, edgeLength);
|
|
tess.y = UnityCalcEdgeTessFactor(pos2, pos0, edgeLength);
|
|
tess.z = UnityCalcEdgeTessFactor(pos0, pos1, edgeLength);
|
|
tess.w = (tess.x + tess.y + tess.z) / 3.0f;
|
|
}
|
|
return tess;
|
|
}
|
|
*/
|