2012-12-04 40 views
1

如何實現2個視口之間的乾淨分離?多個視口乾擾

我有2個視口,一個需要全屏長度,另一個需要小於或等於屏幕尺寸的四分之一(我希望它是一個地圖)。問題在於它們不斷干擾,我從小的視口看到內容。

這裏的display()功能我用:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

glEnable(GL_LIGHTING); 


glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glViewport(0,0,newWidth,newHeight); 
gluPerspective(45,(float)newWidth/(float)newHeight,0.2,500); 
//setup view 
glMatrixMode(GL_MODELVIEW); 

glLoadIdentity(); 

camera.render(crntMode, radiusNew); 

//ground 
glColor3f(0.5,0.5,0.5); 
draw_ground(50,50,2,2,-2); 
... 
... 
... 
glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glViewport(newWidth/2, newHeight/2, newWidth/2, newHeight/2); 
gluPerspective(45,(float)newWidth/(float)newHeight,0.2,500); 

glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 

camera.render(mini_map, radiusNew); 

//ground 
glColor3f(0.5,0.5,0.5); 
draw_ground(50,50,2,2,-2); 
... 
... 
... 
//swap buffers 
glutSwapBuffers(); 

Both viewport cameras are following the character, one from a third person perspective, the other one from top up. It might be harder to see, but the background from the mini-map viewport is interfering with large one (the large on is acting almost as a background for the mini-map). Sometimes the large viewport covers the small viewport.

兩個視攝像機後面的字符,一個從第三人稱視角,從上了另外一個。可能很難看到,但是迷你地圖視口的背景干擾了大型地圖(大型地圖幾乎作爲迷你地圖的背景)。有時,大視口覆蓋小視口。

+3

「*問題是他們不斷干擾*」以什麼方式?這究竟如何體現?你分別畫什麼樣的東西? –

+0

添加了屏幕截圖。我正在捕獲同樣的東西,但使用不同的相機位置。 –

+0

我想說的是,小型視口需要始終處於頂峯。就我而言,我從大視口中抽出的牆壁覆蓋了較小的一個。 –

回答

10

視口不是迷你窗口。視口不過是渲染髮生的主窗口中的一個位置。所有渲染仍然發生在相同的幀緩衝區中。發生問題是因爲兩個視口都使用相同的深度緩衝區。 OpenGL並不知道你希望較大場景中的深度影響較小場景中的渲染。這對OpenGL來說只是一個場景,一個幀緩衝區。

有很多方法來解決這個問題,都具有不同的性能影響/ OpenGL的要求:

  1. 清除與glClear(GL_DEPTH_BUFFER_BIT);呈現兩個場景之間的深度緩衝。這是最簡單的,但在性能方面成本最高。爲了完整起見,我只在這裏列出;你應該改用:

  2. 先畫出你的大場景。然後將視口設置爲較小的場景。關閉深度測試,但請打開glDepthMask。然後繪製一個屏幕對齊的四元組,其中Z是-1,其中四元組的範圍在[X,Y]中爲[-1,1]。對於投影矩陣和模型視圖矩陣,矩陣應該是一致的。這將有效地清除部分場景的深度。

    不要忘了在繪製四邊形之後再進行深度測試。如果需要,也別忘記修復你的矩陣。如果您正在繪製新視口的每個像素(除非您將四邊形的顏色設置爲預期的背景色),這將僅適用。

  3. 先畫出你的大場景。然後使用glScissor to set the scissor box到較小的場景,並使用glEnable(GL_SCISSOR_TEST)來啓用剪刀。之後,用glClear(GL_DEPTH_BUFFER_BIT)清除深度緩衝區。然後禁用剪刀測試並渲染較小的場景。

    這就像#2,除了你不必繪製一個屏幕對齊的四邊形。 glClear在啓用剪刀測試時會考慮剪刀盒,因此它只會清除剪刀區域。

    我提供這個作爲替代,而不是建議的機制,因爲OpenGL實現可以使glClearglScissor行爲錯誤。這應該是首選機制。

  4. 僱用the depth range。這可能會影響你的場景的質量,但它可能是最快的(注意:除非你有真正的理由要關心,否則你不應該在意。也就是說,只有在性能分析顯示性能問題時才這樣做)。對於你的主場景,使用glDepthRange(0.1, 1.0);對於你的小場景,請使用glDepthRange(0.0, 0.1)

    這實際上意味着小場景的所有深度值都將位於大場景的所有深度值的前面。但是,這也意味着您的大場景的深度精度會降低,因此z戰鬥可能很明顯。

    如果您認爲合適,您可以將0.1左右移動;你可以用0.5分割一半的範圍,但我個人建議反對它。小場景不那麼重要,z戰鬥在較小的分辨率下不那麼重要。所以你應該給最重要的場景更精確。

  5. 渲染小場景to an FBO and blit it to the screen。這是最簡單的理由。只需創建一些渲染緩衝區,一個用於顏色,另一個用於深度渲染。將它們粘貼在幀緩衝區對象中。在那裏呈現你的小場景。然後使用glBlitFramebuffer在默認幀緩衝區中將其繪製到您想要的位置。

還有其他方法,如使用模板測試,但這些是你可以依賴的方法。

+0

謝謝,先生!它按照預期工作! –

+1

@ Cookie503:我增加了幾個選項。 –