2013-05-06 69 views
3

我剛剛開始閱讀有關OpenGL的主題,特別是關於Viewing的當前需求。我想了解glFrustum以瞭解我在屏幕上繪製的物體的透視投影,並且據我所知glFrustum會使距離較近的物體更遠的物體更小。
我在這裏使用openFrameworks繪製對象,如Image/Box等和這裏的什麼我試圖做一個簡單的例子:獲取glFrustum的座標

了openFrameworks繪製方法

draw() 
{ 
glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glFrustum(-1.0, 1.0, -1.0, 1.0, 3.0, 500.0); 
glMatrixMode(GL_MODELVIEW); 

sceneImage.draw(0,0,ofGetWidth(), ofGetHeight()); //draw an image on the screen with window's width and dheight 
} 

通過上述glFrustum ,我只是試圖剪切圖像並查看圖像的特定部分以進行初始測試。我不確定glFrustum的那些論據實際上甚至在我從紅皮書的上面鏈接看到有關glFrustum的信息。當然參數是left, right, bottom, top, near, far,但是如何計算1.01.0?我期待屏幕座標在那裏,並嘗試像glFrustum(100, 984, 100, 668,3, 500)但沒有出現在屏幕上。計算glFrustum的參數如何?

+0

認爲你可能想閱讀:http://www.songho.ca/opengl/gl_transform.html – fen 2013-05-06 12:50:10

回答

5

我希望我有你的問題的權利,如果不只是讓我知道,但如果你問「你如何計算glFrustum參數」這是怎麼了:

它實際上所有有關的方面比率和fov。通常你會找到關於如何使用垂直fov製作透視矩陣的信息,但有時候你會想要使用水平fov。因此,繼承人什麼我想出了,我不使用glFrustum但我認爲你可以簡單地切換我perspective函數它,它應該仍然工作:

//-------------------------------------------------------------------------------- 
// set a perspective frustum (right hand) 
// (left, right, bottom, top, near, far) 
//-------------------------------------------------------------------------------- 
void perspective(float l, float r, float b, float t, float n, float f) 
{ 
    m_projection.identity(); 

    m_projection[0] = 2.0f * n/(r - l); 
    m_projection[2] = (r + l)/(r - l); 
    m_projection[5] = 2.0f * n/(t - b); 
    m_projection[6] = (t + b)/(t - b); 
    m_projection[10] = -(f + n)/(f - n); 
    m_projection[11] = -(2.0f * f * n)/(f - n); 
    m_projection[14] = -1.0f; 
    m_projection[15] = 0.0f; 

    update(); 
} 

//-------------------------------------------------------------------------------- 
// set a symmetric perspective frustum 
// ((vertical, degrees) field of view, (width/height) aspect ratio, near, far) 
//-------------------------------------------------------------------------------- 
void perspective_vertical(float fov, float aspect, float front, float back) 
{ 
    fov = DEG_TO_RAD(fov);      // transform fov from degrees to radians 

    float tangent = tanf(fov/2.0f);    // tangent of half vertical fov 
    float height = front * tangent;     // half height of near plane 
    float width = height * aspect;     // half width of near plane 

    perspective(-width, width, -height, height, front, back); 
} 

//-------------------------------------------------------------------------------- 
// set a symmetric perspective frustum 
// ((horizontal, degrees) field of view, (width/height) aspect ratio, near, far) 
//-------------------------------------------------------------------------------- 
void perspective_horizontal(float fov, float aspect, float front, float back) 
{ 
    fov = DEG_TO_RAD(fov);      // transform fov from degrees to radians 
    fov = 2.0f * atanf(tanf(fov * 0.5f)/aspect); // transform from horizontal fov to vertical fov 

    float tangent = tanf(fov/2.0f);    // tangent of half vertical fov 
    float height = front * tangent;     // half height of near plane 
    float width = height * aspect;     // half width of near plane 

    perspective(-width, width, -height, height, front, back); 
} 

而且幫助宏:

#define PI_OVER_180 0.0174532925199432957692369076849f 
#define 180_OVER_PI 57.2957795130823208767981548141f 

#define DEG_TO_RAD(x) (x * PI_OVER_180) 
#define RAD_TO_DEG(x) (x * 180_OVER_PI) 

代碼主要是評論,應該是有道理的,無需進一步解釋它。該參數應該是沿着線的東西:

perspective_horizontal(85.0f /* fov of 85 degrees */, (float)width/height, 0.001f /* using near of 3.0f is kinda too much, just don't use 0.0f */, 1000.0f) 

如果你想要去更深入和實際看到的數字工作,你可以把一些破發點,或printf它,看看它是如何工作的。水平85度相當於垂直約45度。此外,opengl使用列專業,所以如果你最終使用這樣的矩陣,而不是glFrustum確保你首先轉置它。


EDIT(更多關於下面的評論):

讓我們一個窗口,是標準的HD像素-400:(1920-400)寬和(1080-400)高。標準高清的寬高比爲1.77,但-400像素版本爲(1920-400)/(1080-400)= 2.23。

現在調用perspective_horizontal函數的(1920-400)/(1080-400)縱橫比,FOV的85並把一個斷點perspective(...)調用之前是想給我們以下變量:

  • FOV浮0.778087676
  • 方面漂浮2.2352941
  • 前浮標0.00100000005
  • 回浮標100
  • ta ngent浮0.40993762
  • 高度浮子0.000409937638
  • 寬度浮子0.000916331192

注意到,0.000916331192/0.000409937638 = 2.23529412052和0.778087676弧度到度= 44.5811399度垂直,其是85度的水平相當。

而且調用perspective_horizontal函數的(1920-400)/(1080-400)縱橫比的105 FOV,而不是要給我們以下變量:

  • FOV浮1.05568409
  • 方面漂浮2.2352941
  • 前浮0.00100000005
  • 反向浮動100
  • 正切浮動0.583021879
  • 高度浮子0.000583021902
  • 寬度浮子0.00130322541

注意一下再次證明0.00130322541/0.000583021902 = 2.23529408677和1.05568409弧度到度= 60.4862429度垂直它是105度的水平相當。

至於實際的透視矩陣,我不能解釋你的公式是如何工作的,但想象一下gpu中有神奇的獨角獸,如果你餵它們,他們會發生一些神奇的事情,要在屏幕上顯示美麗的東西; 3。


glFrustum也解釋hereherehereherehere,最重要的here

另外一個很好的解釋here

+0

感謝您的答覆。我試圖得到一個不對稱的平截頭體,因爲我選擇使用'glFrustum'。嗯,我仍然覺得在'glFrustum'的解釋中使用'FOV'有點難以理解,因爲'glFrustum'接受所有'座標'作爲原型解釋提到的。 'glPerspective'據我瞭解,我可以明確指定'fov'來獲得透視投影。但是如果我仍然必須使用'fov'來自己計算座標,那麼使用'glFrustum',它是如何工作的? – user1240679 2013-05-06 13:04:05

+0

'glFrustum'要求提及'left,right,bottom,top,near,far'座標,並且看到我指定了'glFrustum(100,984,100,668,3,500)',其中'(100,984)'是'左/右'屏幕座標對我來說,'(100,668)'是'底部/頂部'屏幕協調我。但是很明顯,我在這裏有一個缺口,當我這樣做的時候屏幕上沒有任何東西出現。關於我試圖使用音量剪輯的圖像(如上文所述),我怎麼知道什麼是適當的左,右,底部,頂部座標,以便我得到我想要的圖像裁剪? – user1240679 2013-05-06 13:09:45

+0

@ user1240679絕對沒有理由在glFrustum中使用如此大的數字。你實際上用這些數字定義的是縱橫比和平截頭錐體。基本上你想要的是沿着以下幾條線:左-2右2頂1底-1如果你的屏幕是兩倍寬的高。但它也需要添加fov,所以這些數字不準確。我將在我的答案結尾部分用一些實際數字對其進行擴展。 – 2013-05-06 14:41:54