2012-12-06 39 views
0

我一直在着色器程序中,最奇怪的事情之一正在發生。 我有一個稱爲PositionLightPS的方法,它基本上執行位置光源(全向和聚光燈)的計算,並返回一個包含光線強度和漫反射顏色的結構。HLSL着色器:調用函數更改返回值

它應用在程序先前版本中的工作,但它停止工作由於某種原因...

讓我解釋一下爲什麼。但首先,這是PositionPS方法的代碼。我毫不懷疑,這種方法的計算是正確的,但稍後更多。

struct LightFragment { 
    float4 diffuse; 
    float intensity; 
}; 

LightFragment PositionLightPS(PositionLightVOut pin, float3 lightToPixelVec) 
{ 
    LightFragment result; 

    pin.normal = normalize(pin.normal); 

    float4 diffuse = shaderTexture.Sample(textureSampler, pin.tex0); 
    float3 finalDiffuse = float3(0.0f, 0.0f, 0.0f); 

    float d = length(lightToPixelVec); 
    if(d > plRange) 
    { 
     result.diffuse = float4(finalDiffuse, 0); 
     result.intensity = 0; 
     return result; 
    } 

    lightToPixelVec /= d; 

    result.intensity = dot(lightToPixelVec, pin.normal); 

    if(result.intensity > 0.0f) 
    { 
     finalDiffuse = result.intensity * diffuse.xyz; 
     finalDiffuse.xyz *= clColour.xyz; 
     finalDiffuse.xyz *= clColour.w; 

     finalDiffuse /= plAttenuation[0] + (plAttenuation[1] * d) + (plAttenuation[2] * (d*d)); 
    } 

    result.diffuse = float4(finalDiffuse, diffuse.a) * diffuseColour; 
    return result; 
} 

這是全向光照像素着色器。

float4 OmniLightDiffusePS(PositionLightVOut pin) : SV_TARGET0 
{ 
    float3 lightToPixelVec = plPosition.xyz - pin.worldPos.xyz; 
    return = PositionLightPS(pin, lightToPixelVec).diffuse; 
} 

由於某些原因,儘管已經使用了很長時間,但這並不起作用。但這不是我的問題的重點。奇怪的是,這兩種方法產生不同的結果。

float4 OmniLightDiffusePS(PositionLightVOut pin) : SV_TARGET0 
{ 
    //return float4(1,1,1,1); 
    float3 lightToPixelVec = plPosition.xyz - pin.worldPos.xyz; 
    LightFragment fragment = PositionLightPS(pin, lightToPixelVec); 
    return float4(1,1,1,1); 
} 

這人會返回一個黑色像素

float4 OmniLightDiffusePS(PositionLightVOut pin) : SV_TARGET0 
{ 
    return float4(1,1,1,1); 
    float3 lightToPixelVec = plPosition.xyz - pin.worldPos.xyz; 
    LightFragment fragment = PositionLightPS(pin, lightToPixelVec); 
    //return float4(1,1,1,1); 
} 

這人會返回一個白色像素

因此,這意味着調用PositionLightPS方法對價值的影響返回......但爲什麼? 爲什麼呢?發生什麼事?這是內存錯誤嗎?

(注意:直接在OmniLightDiffuse方法複製PositionLightPS方法代碼解決了這個問題,並且光顯示器通常這意味着在PositionLightPS執行的計算是正確的問題是然後,不使用LightFragment struct以某種方式對着色器程序產生影響?)

回答

2

我找到了問題的原因。我的電腦使用CUDA,並在我不知情的情況下鎖定使用集成圖形芯片。強制NVidia卡解決了問題。

但是,我確實發現了這個非常有用的博客文章,其中詳細介紹了本質上是我的問題。 當兩個特定的編譯器標誌同時激活時,調用用戶定義函數會導致編譯器的內聯刪除它所處理的像素。 我不知道集成圖形芯片是否重現了這個確切的錯誤,但症狀看起來完全一致(即,調用一個沒有發生返回值的函數會改變返回的東西)。

有關更多詳細信息,請參閱Nico Shertler的博客文章鏈接:http://nicoschertler.wordpress.com/2012/01/02/hlsl-4-calls-to-user-defined-functions-will-crash/

1

通常情況下,這是由於除零錯誤。 ATI和NVIDIA在處理這款NaN方面可能會有所不同。檢查輸入矢量的長度,或添加一些epsilon。