2012-03-29 40 views
0

我正在爲OpenGL應用程序實現我自己的矩陣數學。到目前爲止,事情雖然很困難,但基本上很好。我最近的一個問題,我沒有得到一個解釋或一個特定問題的運氣,指出了我,是做我的glOrtho()的實現。我的glOrtho有什麼問題?負零而不是零

具體來說,我的版本導致matrix [14]元素爲負零。 (-0.000000),而使用棄用的glOrtho()後,我從OpenGL獲得的glGet()版本是正常的零。 (0.000000)

我不知道這是否影響到任何事情,但我被我的數學不匹配打擾。

glOrtho的OpenGL規格,僅供參考,我相信我下面的正確,並正確地做數學爲: http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml

我自己glOrtho功能:

vec_t* Utils::OrthoMatrix(vec_t* out_matrix, const vec_t& left, const vec_t& right, const vec_t& bottom, const vec_t& top, const vec_t& znear, const vec_t& zfar) 
{ 
    memcpy(out_matrix, zeroMatrix, 16*sizeof(vec_t)); 

    out_matrix[0] = 2.0f/(right - left); 
    out_matrix[5] = 2.0f/(top - bottom); 
    out_matrix[10] = -2.0f/(zfar - znear); 
    out_matrix[12] = -((right + left)/(right - left)); 
    out_matrix[13] = -((top + bottom)/(top - bottom)); 
    out_matrix[14] = -((zfar + znear)/(zfar - znear)); 
    out_matrix[15] = 1.0f; 

    return out_matrix; 
}

我的尺寸調整功能(剝離向下大幅提高可讀性):

void GameLogic::OnResize(int width, int height) // For purposes of this test, width = 640, height = 480. 
{ 
    if(height == 0) // Avoid potential divide-by-zero 
     height = 1; 

    glViewport(0, 0, width, height); 

    Utils::OrthoMatrix(m_orthoMatrix, 0.0f, (GLfloat)width, (GLfloat)height, 0.0f, -100.0f, 100.0f); 

    // Setup fixed function OpenGL to compare against. 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrtho(0.0f, (GLfloat)width, (GLfloat)height, 0.0f, -100.0f, 100.0f); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
}
void GameLogic::Render() // Drastically cut down to illustrate issue. 
{ 
    vec_t modelviewmatrix[16], projectionmatrix[16]; 
    glGetFloatv(GL_MODELVIEW_MATRIX, modelviewmatrix); 

    glGetFloatv(GL_PROJECTION_MATRIX, projectionmatrix); 
/* 
    At this point, projectionmatrix and m_orthoMatrix are identical, 
    except in the matrix[14] element, which is 0.000000 for projectionmatrix, 
    and -0.000000 for m_orthoMatrix. 
*/ 
}

我無法弄清楚爲什麼會這樣,或者它會產生什麼影響?數學檢查正確,據我所知,所以它應該是負的零,但OpenGL返回正零。到目前爲止,我的最佳猜測是駕駛員爲了避免零負值而欺騙數字的某種驅動器怪癖?我已經在兩個獨立的nVidia GPU上測試了這個代碼,並得到了相同的結果。無法訪問某些ATI或類似軟件以進行測試。

聲明:我對glOrtho的near和far值如何工作有些無知,儘管規範確實規定允許使用負值。

我應該用單位矩陣初始化投影矩陣,還是將單位矩陣乘以透視矩陣?我不認爲我需要這樣做,而我的glFrustum實現似乎沒有這樣做就可以正常工作,但也許是這樣嗎?我不太瞭解這個數學是否足以知道是否應該做正確與否。

任何想法,任何人,我在做什麼錯誤或誤解?或者如果我確實發現了某種奇怪的怪癖?如果有人建議最好的方法是採用負值,那麼使用負值可能會產生什麼效果也是很好的解釋,而不是試圖調整我目前得到的值。

回答

1

不要試圖「修復」它 - 你的代碼工作正常。我想,「奇怪的怪癖」很好地覆蓋了它。

將零加到除零以外的任何值(這是矩陣乘法的作用)會得出完全相同的結果;這甚至不算作重大差異。

而實際上,當比較計算相同標稱結果的兩個不同浮點過程時,您應該在期望遇到差異。浮點不精確,所以你做不同的任何事情(例如改變加法的順序)可能會產生稍微不同的結果。因此,無論何時您比較浮點結果,都需要指定容差。

+0

謝謝你這麼好地解釋你的答案。幫助我更多地瞭解正在發生的事情和原因。 – Azuvector 2012-03-30 03:36:44

3

CPU和GPU內部的浮點精度不一定相同,所以預計會有微小的差異。

0

負零和正零在數學上是相同的浮點值。他們不是等於,但根據IEEE-754你會得到同樣的結果。

您不應該嘗試將等式與不同的浮點計算完全匹配。如果你需要檢查矩陣數學,那麼至少要測試一個範圍(加號或減號)。

+0

實際上,我認爲標準說+0和-0 *是相等的(就比較而言,無論如何)。 – comingstorm 2012-03-29 17:26:48