2012-01-25 47 views
10

我有這個奇怪的問題,我希望有人可以爲我清除這個,所以我可以明白什麼是錯的,並採取相應的行動。在OpenGL(固定功能)中,我正在渲染一個帶有正投影內表面的管。Opengl透視失真

下圖顯示了結果。它由4個頂點組成,這些頂點使用左側顯示的索引模式形成三角形。爲了您的方便,我在管上標記了頂點。在右邊是正在使用的質地:

enter image description here

正如你可以看到紋理被嚴重的失真。當我最初創建了只有2個頂點環的管時,我認爲提高環的數量可以修復失真,但沒有喜悅。 glHint似乎也不會影響這個特定的問題。

紋理座標似乎沒問題。此外,檢查器模式似乎可以正確渲染,但我想失真在這種非常特定的模式下是不可見的。

請忽略交叉線,因爲其中一條邊是不存在的;我通過GL_LINE_LOOP渲染了線框。

+0

這是因爲您使用的是正射投影嗎? – geofftnz

回答

2

這種特殊效果是由紋理座標在三角形中插值的方式引起的。發生的是,一個方向成爲主要組成部分,而另一個方向則偏斜。你的標本碰巧很容易發生這種情況。這也恰好是地板或牆壁上的透視投影和紋理問題。你需要的是所謂的「視角正確紋理」PCT。有一個glHint這個,但我想,你已經試過了。

坦率地說,避免這種情況的唯一方法是通過細分來應用透視校正。幸運的是,這對於基於四邊形的geoemtry(就像你的)很容易。細分邊緣時,沿所有4條邊在細分中心處插值紋理座標,並使用其中4條邊的平均值。僅沿着一條邊插補紋理座標正是您想要避免的。

如果您想保持幾何數據不變,您可以在片段着色器中實現PCT。

+0

雖然我嘗試添加更多戒指,但我沒有嘗試每個戒指添加更多頂點,這解決了問題。所以確實,細分是要走的路。謝謝! –

0

嘗試一些分區:

template< typename Vec > 
void glVec2d(const Vec& vec) 
{ 
    glVertex2f(static_cast<float>(vec.x()) , static_cast<float>(vec.y())); 
} 

template< typename Vec > 
void glTex2d(const Vec& vec) 
{ 
    glTexCoord2f(static_cast<float>(vec.x()) , static_cast<float>(vec.y())); 
} 

template< typename Vec > 
void glQuad 
    (
    const Vec& A, 
    const Vec& B, 
    const Vec& C, 
    const Vec& D, 
    unsigned int divs = 2, 
    const Vec& At = Vec(0,0), 
    const Vec& Bt = Vec(1,0), 
    const Vec& Ct = Vec(1,1), 
    const Vec& Dt = Vec(0,1) 
    ) 
{ 
    // base case 
    if(divs == 0) 
    { 
     glTex2d(At); 
     glVec2d(A); 

     glTex2d(Bt); 
     glVec2d(B); 

     glTex2d(Ct); 
     glVec2d(C); 

     glTex2d(Dt); 
     glVec2d(D); 

     return; 
    } 

    Vec AB = (A+B) * 0.5; 
    Vec BC = (B+C) * 0.5; 
    Vec CD = (C+D) * 0.5; 
    Vec AD = (A+D) * 0.5; 
    Vec ABCD = (AB+CD) * 0.5; 

    Vec ABt = (At+Bt) * 0.5; 
    Vec BCt = (Bt+Ct) * 0.5; 
    Vec CDt = (Ct+Dt) * 0.5; 
    Vec ADt = (At+Dt) * 0.5; 
    Vec ABCDt = (ABt+CDt) * 0.5; 

    // subdivided point layout 
    // D CD C 
    // 
    // AD ABCD BC 
    // 
    // A AB B 

    // subdivide 
    glQuad2d(A, AB, ABCD, AD, divs - 1, At, ABt, ABCDt, ADt); 
    glQuad2d(AB, B, BC, ABCD, divs - 1, ABt, Bt, BCt, ABCDt); 
    glQuad2d(ABCD, BC, C, CD, divs - 1, ABCDt, BCt, Ct, CDt); 
    glQuad2d(AD, ABCD, CD, D, divs - 1, ADt, ABCDt, CDt, Dt); 
} 

我通常使用Eigen::Vector2fVec

0

爲什麼你使用正射投影呢?如果您使用透視投影,則OpenGL將爲您更正紋理貼圖。