2012-10-29 55 views
5

我發現如果我將透視矩陣的遠平面距離定義爲1,000,000,000,那麼該範圍內的所有對象都會被剪切掉。 100,000,000的範圍工作正常。 任何人都可以解釋這一點?我的意思是,它仍然不近似浮點數最大範圍。或者我錯了嗎?爲了計算透視圖,我使用GLM庫。沒有固定的管道僵硬。OpenGL遠平面給出非常大的值剪輯所有內容

UPDATE:(JAVA) 投影矩陣計算:

public static Mat4 perspective(float fovy, float aspect, float zNear, float zFar) { 
    float range = (float) (Math.tan(Math.toRadians(fovy/2.0f)) * zNear); 
    float left = -range * aspect; 
    float right = range * aspect; 
    float bottom = -range; 
    float top = range; 

    Mat4 res = new Mat4(0.0f); 

    res.matrix[0] = (2.0f * zNear)/(right - left); 
    res.matrix[5] = (2.0f * zNear)/(top - bottom); 
    res.matrix[10] = -(zFar + zNear)/(zFar - zNear); 
    res.matrix[11] = -1.0f; 
    res.matrix[14] = -(2.0f * zFar * zNear)/(zFar - zNear); 

    return res; 
    } 
+2

不知道我理解的問題,而是一個單精度浮點數可以代表超過700位小數一點。你的號碼有10位數字,所以只有最後3位不同的座標是「相同的」。所以,999,999,950可能會被剪輯。那是你想知道的嗎? – Damon

+1

聽起來像一個舍入問題或類似的東西。當然它不會跨越浮點範圍(它甚至不會跨越32位int範圍)。但是除以這麼大的數字可能會將所有數據都變爲0.同樣,當向這個大數字添加一些非常小的數字時(例如在矩陣計算期間完成的「near + far」或「near-far」),數字最有可能保持不變。需要分析它如何影響矩陣的計算。 –

+0

謝謝你的回答。但是你上面的一個人說的是相反的。 –

回答

8

你們看到的是一個四捨五入的問題,由於浮點數的非常有限精度。

雖然浮點數有很大的(對於大多數實際應用「無限」)範圍,但它們的精度有限,遠低於相同大小的整數。單精度(32位)float可以代表超過7位十進制數字。你可以有非常小的或大的(比你想象的更小更大的)數字,但它們仍然只有7.22有效的十進制數字。

唯一號碼所能表述爲999999900和1000000100之間的單精度float是:999999872,999999936,10億,並且1000000064.可以很容易地通過在for循環計數的整數變量,澆鑄到float可變驗證這一點,和打印它。

這意味着,例如999,999,950和999,999,951和999,999,999是完全相同的數字,因此999,999,950可能會被裁剪,儘管它顯然位於裁剪平面的前方。

編輯:與輸出

小演示程序:

#include <stdio.h> 

int main() 
{ 
    float f = 0.0f; 
    for(int i = 999999900; i < 1000000100; ++i) 
    { 
     f = i; 
     printf("%d\t%f\n", i, f); 
    } 
    return 0; 
} 

999999900  999999872.000000 
999999901  999999872.000000 
999999902  999999872.000000 
999999903  999999872.000000 
999999904  999999872.000000 
999999905  999999936.000000 
999999906  999999936.000000 
999999907  999999936.000000 
... 
[some lines omitted] 
... 
999999967  999999936.000000 
999999968  1000000000.000000 
999999969  1000000000.000000 
999999970  1000000000.000000 
999999971  1000000000.000000 
999999972  1000000000.000000 
... 
[some lines omitted] 
... 
1000000028  1000000000.000000 
1000000029  1000000000.000000 
1000000030  1000000000.000000 
1000000031  1000000000.000000 
1000000032  1000000000.000000 
1000000033  1000000064.000000 
1000000034  1000000064.000000 
1000000035  1000000064.000000 
1000000036  1000000064.000000 
1000000037  1000000064.000000 
1000000038  1000000064.000000 
1000000039  1000000064.000000 
1000000040  1000000064.000000 
1000000041  1000000064.000000 
1000000042  1000000064.000000 
1000000043  1000000064.000000