2016-01-13 67 views
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或任何類似的網頁上找到任何信息。

謝謝

+0

我能想到的唯一的事情是'pow'變體產生'NaN'值,可能是由於對'2'的優化。如果它沒有出現在調試器中,您可以嘗試添加返回值的「isnan」檢查並寫入UAV,您可以讀回並在CPU上打印。或者直接將返回值寫入無人機。 – MooseBoys

+0

感謝您的回答。我已經試過了,pow功能似乎沒問題。經過一些進一步的試驗和錯誤,我發現問題是tessFactors。不知何故,價值組合必須有一些限制。我已經將insideTessFactor的行改爲pt.InsideTess [0] = max(pt.EdgeTess [0] [3]));它工作沒有任何問題。沒有在msdn或類似網頁上發現任何評論。 – kaiser

+0

由於有新信息而改變了描述 – kaiser

回答

0

最新的驅動程序更新解決了問題。