细分阶段内tessFactors的奇怪行为

时间:2016-01-13 00:54:22

标签: directx-11 hlsl tessellation

我注意到我的nvidia 860m有一些超级行为。我编写了一些3D引擎,并且我使用曲面细分进行地形渲染。

我使用简单的四边形曲面细分算法。

struct PatchTess
{
    float EdgeTess[4] : SV_TessFactor;
    float InsideTess[2] : SV_InsideTessFactor;
};

PatchTess ConstantHS(InputPatch<VS_OUT, 4> patch)
{
    PatchTess pt;

    float3 l = (patch[0].PosW + patch[2].PosW) * 0.5f;
    float3 t = (patch[0].PosW + patch[1].PosW) * 0.5f;
    float3 r = (patch[1].PosW + patch[3].PosW) * 0.5f;
    float3 b = (patch[2].PosW + patch[3].PosW) * 0.5f;
    float3 c = (patch[0].PosW + patch[1].PosW + patch[2].PosW + patch[3].PosW) * 0.25f;

    pt.EdgeTess[0] = GetTessFactor(l);
    pt.EdgeTess[1] = GetTessFactor(t);
    pt.EdgeTess[2] = GetTessFactor(r);
    pt.EdgeTess[3] = GetTessFactor(b);

    pt.InsideTess[0] = GetTessFactor(c);
    pt.InsideTess[1] = pt.InsideTess[0];

    return pt;
}

[domain("quad")]
[partitioning("fractional_even")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(4)]
[patchconstantfunc("ConstantHS")]
[maxtessfactor(64.0f)]
VS_OUT HS(InputPatch<VS_OUT, 4> p, uint i : SV_OutputControlPointID)
{
    VS_OUT vout;
    vout.PosW = p[i].PosW;
    return vout;
}

[domain("quad")]
DS_OUT DS(PatchTess patchTess, float2 uv : SV_DomainLocation, const OutputPatch<VS_OUT, 4> quad)
{
    DS_OUT dout;

    float3 p = lerp(lerp(quad[0].PosW, quad[1].PosW, uv.x), lerp(quad[2].PosW, quad[3].PosW, uv.x), uv.y);
    p.y = GetHeight(p);

    dout.PosH = mul(float4(p, 1.0f), gViewProj);
    dout.PosW = p;
    return dout;
}

上面的代码不是问题,只是想给你一些代码上下文。

此功能出现问题:

inline float GetTessFactor(float3 posW)
{
    const float factor = saturate((length(gEyePos - posW) - minDistance) / (maxDistance - minDistance));
    return pow(2, lerp(6.0f, 0.0f, factor));
}

当我在Visual Studio中使用调试模式时,一切都很有效,曲面细分可以正常工作。但在发布模式下,我得到了地形补丁的闪烁。

现在超级奇怪的事情:当我改变功能并从pow切换到线性函数或其他东西时,一切都如预期的那样起作用。 所以这很好用:

inline float GetTessFactor(float3 posW)
{
    const float factor = saturate((length(gEyePos - posW) - minDistance) / (maxDistance - minDistance));
    return lerp(64.0f, 0.0f, factor));
}

编辑: 换行:

pt.InsideTess[0] = GetTessFactor(c);

pt.InsideTess[0] = max(max(pt.EdgeTess[0], pt.EdgeTess[1]), max(pt.EdgeTess[2], pt.EdgeTess[3]));

完成这项工作。

似乎有时pow函数计算的值(有效范围为64.0f)对边缘tess因子无效。

另请注意,在发布模式下运行而不是在调试模式(VS 2013)中,此问题才会出现。

有没有人知道对tessfactor值组合的限制?我没有在msdn或任何类似页面上找到任何信息。

由于

1 个答案:

答案 0 :(得分:0)

最新的驱动程序更新解决了问题。