我注意到我的 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)。
另请记住,此问题仅在以发布模式而不是在调试模式(VS 2013)下运行时出现。
有谁知道 tessfactor 值组合的限制?我没有在 msdn 或任何类似页面上找到任何信息。
谢谢