2015-09-21 40 views
0

爲了學習opengl,我使用openGL 3.3創建了一個簡單的3D圖形引擎。我最近在距離上增加了光衰減;這已將所有物體完全變黑。這是通過在片段着色器中加入以下代碼,以我的光計算完成:什麼可能導致變量表現爲無限且同時爲非無限?

float distance = length(lite.position - FragPos); 
float attenuation = 1.0f/(lite.constant + (lite.linear * distance) + (lite.quadratic * (distance * distance))); 
ambient *= attenuation; 
diffuse *= attenuation; 
specular *= attenuation; 

result += (ambient + diffuse + specular); 

似乎可以認爲attenuation非常小,有效地或實際0或負(黑色)。爲了測試這個,我使用result += vec3(attenuation);,結果是白色物體;這表明attenuation不是接近0,而是1.0或更大;嘗試result += vec3(attenuation/500000);的附加測試仍會產生白色,這表明衰減非常大,可能是無限的。我做了一些無限和NaN檢查。 NaN支票告訴我這是一個數字,無限檢查告訴我它有時是無限的,有時不是。事實上,它告訴我,它既是無限的,也是無限的。我通過使用以下代碼段確定了這一點:

if(isinf(attenuation)){ 
    result += vec3(1.0, 0.0, 0.0); 
} 
if(isinf(attenuation) && !isinf(attenuation)){ 
    result += vec3(0.0, 1.0, 0.0); 
} 
if(!isinf(attenuation)){ 
    result += vec3(0.0, 0.0, 1.0); 
} 

我的對象變成紫色/洋紅色。如果attenuation無限,我會希望我的物體呈現紅色;如果它們不是無限的,我會期望它們顯得藍色;他們在某種程度上既是無限的,也是無限的,我希望他們看起來很綠。如果我使result += ...result = ...,則對象顯示爲紅色。在這種情況下,如果我的紫色物體暗示result將首先設置爲紅色,然後設置爲藍色,導致藍色物體(如果以某種方式綠色檢查失敗),它既是無限的,也不是無限的。

我希望這能說明我的困惑之源。我的測試顯示attenuation是無限的,並且它不是無限的,並且它既不是。

頂部事事休,當我使用:

float attenuation = 1.0f/(1.0 + (0.0014 * distance) + (0.000007* (distance * distance))); 

確定衰減係數,一切工作完全按照預期;但是這裏顯示爲常數的值是什麼是從我的OpenGL調用(C++)傳遞:

glUniform1f(lightConstantLoc, 1.0f); 
glUniform1f(lightLinearLoc, 0.0014f); 
glUniform1f(lightQuadraticLoc, 0.000007f); 

從那裏我應該得出結論,我的數據沒有被交付給我的着色器正確的,但我相信我的lite.constant等值已被正確設置,並且distance是合理的值。當我挑選每一個出來的顏色,對象也把那color.ie:使用此

result = vec3(lite.constant, 0.0, 0.0); 

我的對象會變成紅色一些陰影,爲lite.constantlite.linear

搜索谷歌和堆棧對於像「glsl isinf true and false」或「glsl variable is is and is not infinite」這樣的東西溢出來,我絕對沒有相關的結果。

我明白我對這裏發生的事情,或者某種方式有效的方式,我是完全無知的。所以我轉向你,我是否錯過了一些明顯的東西,這樣做是錯誤的,還是這是一個真正的謎團?

+0

你能否在你的測試中預先設置'result'到vec3(0,0,0),以確保它不是事先搞定的值? (洋紅色沒有意義) –

+0

@Clairvoire感謝您提及重置'result',它將我的注意力引向瞭解決方案。在遍歷所有光源的循環之前,「結果」被設置爲「vec3(0.0)」。問題是,循環迭代次數多於燈光,因此它使用的是不存在的數據。我會很快發佈一個答案。 – Jing

回答

0

問題出在問題中沒有顯示的代碼。 關鍵信息是我的着色器支持多達5個光源,並遍歷所有5個光源;即使提供的光源少於5個時也是如此。考慮到這一點改變

vec3 result = vec3(0.0); 
for(int i = 0; i < 5; ++i){ 
    Light lite = light[i]; 
    ... 

vec3 result = vec3(0.0); 
for(int i = 0; i < 1; ++i){ 
    Light lite = light[i]; 
    ... 

解決了這個問題,並且現在的一切表現完美。看來,不存在的數據既不是無限的,也不是有限的;這在一定程度上是有意義的。

0

我不確定爲什麼你的衰減是如此之大,但你的解釋是/是不是無限的問題很簡單 - 至少attenuation的一個組件是無限的,而至少有一個其他組件是不。

當你做if (bvec) - 測試一個條件是一個布爾向量而不是一個布爾值 - 它的行爲就像你做了if (any(bvec))。因此,如果任何組件都爲真,它將執行關聯的真正分支。當你有isinf(attenuation)時,你會得到一個布爾向量。例如,如果紅色是無限的而其他的不是,你會得到(true,false,false)。所以!isinf(attenuation)將是(false,true,true),而中間if&&的結果是(false,false,false)。

因此它執行第一個和第三個if(而不是第二個),給你洋紅色。

+0

在發佈的代碼中,「衰減」是一個標量浮點數。這個解釋是否真的適用於標量值的情況? –

+0

這將完美地描述問題,是「衰減」的一個向量,但正如已經指出的那樣,「衰減」實際上是一個「浮點」/標量。這個解釋是否適用,或者有沒有辦法將我的'float'混淆爲'bvec'? – Jing

相關問題