1
\$\begingroup\$

i'm trying to a mesh tessellate with dx11 with the tessellation factor calculated by the size of the triangle and the distance to the screen.

I do the same operation on the 3 edges of the triangle, so i would expect i get the same level of tesselation on the other triangle that shares the edge, but it seems like it doesn't. Does anyone have an idea why this doesn't work like expected?

I need the same amount of tessellation on the other side of the edge to do displacement mapping without any cracks.

There are 5 triangles in this image, the red "circle" is around 2 edges shared by 4 of the triangles in pairs. tesselation problem

float calcLod(float3 a, float3 b)
{
    float dist = distance(a,b) ; 

    float3 center = (b+a)/2;

    float camDist = distance(CameraPosition, center);

    return dist * tesselationStrength / camDist;
}

hullShaderConstantOutput hullShaderConstant( InputPatch<vertexShaderOutput, 3> ip, uint pid : SV_PrimitiveID )
{
    hullShaderConstantOutput output;
// get worldspace positions
    float3 v0 = ip[0].position;
    float3 v1 = ip[1].position;
    float3 v2 = ip[2].position;


    output.edges[0] = calcLod(v0, v1);
    output.edges[1] = calcLod(v1, v2);
    output.edges[2] = calcLod(v2, v0); 

    output.inside = (output.edges[0] + output.edges[1] + output.edges[2])/3;

    return output;
}

[domain("tri")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("hullShaderConstant")]
hullShaderOutput hullShader( InputPatch<vertexShaderOutput, 3> input, uint pointId : SV_OutputControlPointID, uint pid : SV_PrimitiveID )
{
    hullShaderOutput output;
    output.position = input[pointId].position;
    output.uv = input[pointId].uv;
    output.tangentToWorld = input[pointId].tangentToWorld;
    return output;
}
\$\endgroup\$
1
\$\begingroup\$

I also tried to create my own algorithm for tessellation, but it produced micro-cracking, then found this (on AMD's site if I recall correctly), which works like a charm:

cbuffer tessBuf:register(b0)
{
    float4 g_f4Eye; //camera position in world space
    float4 g_f4TessFactors; //constant tessfactors (from a material for example)
};

struct ConstantOutputType
{
    float fTessFactor[3] : SV_TessFactor;
    float fInsideTessFactor : SV_InsideTessFactor;
 //other outputs beside tessfactors
}

ConstantOutputType PatchConstantFunction(InputPatch<HullInputType, 3> I)
{
    ConstantOutputType O = (ConstantOutputType)0;

static const float MODIFIER = 0.6f;

    float fDistance;
    float3 f3MidPoint;
    // Edge 0
    f3MidPoint = ( I[2].f3Position + I[0].f3Position ) / 2.0f;
    fDistance = distance( f3MidPoint, g_f4Eye.xyz )*MODIFIER - g_f4TessFactors.z;
    O.fTessFactor[0] = g_f4TessFactors.x * ( 1.0f - clamp( ( fDistance / g_f4TessFactors.w ), 0.0f, 1.0f - ( 1.0f / g_f4TessFactors.x ) ) );
    // Edge 1
    f3MidPoint = ( I[0].f3Position + I[1].f3Position ) / 2.0f;
    fDistance = distance( f3MidPoint, g_f4Eye.xyz )*MODIFIER - g_f4TessFactors.z;
    O.fTessFactor[1] = g_f4TessFactors.x * ( 1.0f - clamp( ( fDistance / g_f4TessFactors.w ), 0.0f, 1.0f - ( 1.0f / g_f4TessFactors.x ) ) );
    // Edge 2
    f3MidPoint = ( I[1].f3Position + I[2].f3Position ) / 2.0f;
    fDistance = distance( f3MidPoint, g_f4Eye.xyz )*MODIFIER - g_f4TessFactors.z;
    O.fTessFactor[2] = g_f4TessFactors.x * ( 1.0f - clamp( ( fDistance / g_f4TessFactors.w ), 0.0f, 1.0f - ( 1.0f / g_f4TessFactors.x ) ) );
    // Inside
    O.fInsideTessFactor = ( O.fTessFactor[0] + O.fTessFactor[1] + O.fTessFactor[2] ) / 3.0f;


//Then pass the other members of the outputtype
}

Hope it helps!

\$\endgroup\$
  • \$\begingroup\$ wah, serious, Edge 0 is vertex 2 and 0? so my edges are just shifted, lets try. Thanks, it's really hard to find the correct order for the edge factors. \$\endgroup\$ – Stijn Tallon Jan 18 '14 at 17:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.