0
我注意到了我的nvidia 860m上的一些超級stange行爲。我編程一些3D引擎,我正在使用曲面細分進行地形渲染。Tessellation階段tessFactors的奇怪行爲
我使用簡單的四邊形細分算法。
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;
}
上面的代碼不是問題,只是想給你一些代碼上下文。
的問題occurres在這個函數:
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中,一切工作得FINDE中,細分的工作,因爲它應該。但在發佈模式下,我得到了地形補丁閃爍。
現在超級奇怪的事情:當我改變功能並從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或任何類似的網頁上找到任何信息。
謝謝
我能想到的唯一的事情是'pow'變體產生'NaN'值,可能是由於對'2'的優化。如果它沒有出現在調試器中,您可以嘗試添加返回值的「isnan」檢查並寫入UAV,您可以讀回並在CPU上打印。或者直接將返回值寫入無人機。 – MooseBoys
感謝您的回答。我已經試過了,pow功能似乎沒問題。經過一些進一步的試驗和錯誤,我發現問題是tessFactors。不知何故,價值組合必須有一些限制。我已經將insideTessFactor的行改爲pt.InsideTess [0] = max(pt.EdgeTess [0] [3]));它工作沒有任何問題。沒有在msdn或類似網頁上發現任何評論。 – kaiser
由於有新信息而改變了描述 – kaiser