2012-04-06 135 views
2

我正在製作一個基於體素的遊戲,並且爲了它的需要,我創建了一個塊渲染引擎。如何停止渲染不可見面

問題是,我需要生成很多立方體。每次我渲染16x16x16塊以上的塊時,我的FPS幾乎沒有下降,因爲它渲染了所有這些立方體的全部6個面。這是24 576四邊形,我不想那樣。因此,我的問題是,如何停止渲染不可見的頂點(或四邊形),並因此提高我的遊戲性能?

下面是渲染塊類:

public void renderBlock(int posx, int posy, int posz) { 
    try{ 
    //t.bind(); 
    glEnable(GL_CULL_FACE); 
    glCullFace(GL_BACK);// or even GL_FRONT_AND_BACK */); 

    glPushMatrix(); 

    GL11.glTranslatef((2*posx+0.5f),(2*posy+0.5f),(2*posz+0.5f));    // Move Right 1.5 Units And Into The Screen 6.0 
    GL11.glRotatef(rquad,1.0f,1.0f,1.0f); 

    glBegin(GL_QUADS);    // Draw A Quad 

    GL11.glColor3f(0.5f, 0.4f, 0.4f);    // Set The Color To Green 
    GL11.glTexCoord2f(0,0); 
    GL11.glVertex3f(1f, 1f,-1f);   // Top Right Of The Quad (Top) 
    GL11.glTexCoord2f(1,0); 
    GL11.glVertex3f(-1f, 1f,-1f);   // Top Left Of The Quad (Top) 
    GL11.glTexCoord2f(1,1); 
    GL11.glVertex3f(-1f, 1f, 1f);   // Bottom Left Of The Quad (Top) 
    GL11.glTexCoord2f(0,1); 
    GL11.glVertex3f(1f, 1f, 1f);   // Bottom Right Of The Quad (Top) 

    //GL11.glColor3f(1.2f,0.5f,0.9f);    // Set The Color To Orange 
    GL11.glTexCoord2f(0,0); 
    GL11.glVertex3f(1f,-1f, 1f);   // Top Right Of The Quad (Bottom) 
    GL11.glTexCoord2f(0,1); 
    GL11.glVertex3f(-1f,-1f, 1f);   // Top Left Of The Quad (Bottom) 
    GL11.glTexCoord2f(1,1); 
    GL11.glVertex3f(-1f,-1f,-1f);   // Bottom Left Of The Quad (Bottom) 
    GL11.glTexCoord2f(1,0); 
    GL11.glVertex3f(1f,-1f,-1f);   // Bottom Right Of The Quad (Bottom) 

    //GL11.glColor3f(1.0f,0.0f,0.0f);    // Set The Color To Red 
    GL11.glTexCoord2f(0,0); 
    GL11.glVertex3f(1f, 1f, 1f);   // Top Right Of The Quad (Front) 
    GL11.glTexCoord2f(1,0); 
    GL11.glVertex3f(-1f, 1f, 1f);   // Top Left Of The Quad (Front) 
    GL11.glTexCoord2f(1,1); 
    GL11.glVertex3f(-1f,-1f, 1f);   // Bottom Left Of The Quad (Front) 
    GL11.glTexCoord2f(0,1); 
    GL11.glVertex3f(1f,-1f, 1f);   // Bottom Right Of The Quad (Front) 

    //GL11.glColor3f(1f,0.5f,0.0f);    // Set The Color To Yellow 
    GL11.glTexCoord2f(0,0); 
    GL11.glVertex3f(1f,-1f,-1f);   // Bottom Left Of The Quad (Back) 
    GL11.glTexCoord2f(1,0); 
    GL11.glVertex3f(-1f,-1f,-1f);   // Bottom Right Of The Quad (Back) 
    GL11.glTexCoord2f(1,1); 
    GL11.glVertex3f(-1f, 1f,-1f);   // Top Right Of The Quad (Back) 
    GL11.glTexCoord2f(0,1); 
    GL11.glVertex3f(1f, 1f,-1f);   // Top Left Of The Quad (Back) 

    //GL11.glColor3f(0.0f,0.0f,0.3f);    // Set The Color To Blue 
    GL11.glTexCoord2f(0,1); 
    GL11.glVertex3f(-1f, 1f, 1f);   // Top Right Of The Quad (Left) 
    GL11.glTexCoord2f(1,1); 
    GL11.glVertex3f(-1f, 1f,-1f);   // Top Left Of The Quad (Left) 
    GL11.glTexCoord2f(1,0); 
    GL11.glVertex3f(-1f,-1f,-1f);   // Bottom Left Of The Quad (Left) 
    GL11.glTexCoord2f(0,0); 
    GL11.glVertex3f(-1f,-1f, 1f);   // Bottom Right Of The Quad (Left) 

    //GL11.glColor3f(0.5f,0.0f,0.5f);    // Set The Color To Violet 
    GL11.glTexCoord2f(0,0); 
    GL11.glVertex3f(1f, 1f,-1f);   // Top Right Of The Quad (Right) 
    GL11.glTexCoord2f(1,0); 
    GL11.glVertex3f(1f, 1f, 1f);   // Top Left Of The Quad (Right) 
    GL11.glTexCoord2f(1,1); 
    GL11.glVertex3f(1f,-1f, 1f);   // Bottom Left Of The Quad (Right) 
    GL11.glTexCoord2f(0,1); 
    GL11.glVertex3f(1f,-1f,-1f);   // Bottom Right Of The Quad (Right) 

    //rquad+=0.0001f; 
    glEnd(); 
    glPopMatrix(); 
    }catch(NullPointerException t){t.printStackTrace(); System.out.println("rendering block failed");} 
} 

這裏是代碼,使他們:

private void render() { 
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT|GL11.GL_DEPTH_BUFFER_BIT); 
    for(int y=0; y<32; y++){ 
    for(int x=0; x<16; x++){ 
     for(int z=0; z<16; z++) { 
     b.renderBlock(x, y, z); 

     } 
    } 
    } 
} 
+0

任何人都可以幫忙嗎? – TheMorfeus 2012-04-06 15:49:59

+0

可能的重複[如何去除單位立方體世界中的臉部去除Minecraft?](http://stackoverflow.com/questions/6319655/how-to-do-face-removal-in-a-unit- cube-world-a-la-minecraft) – 2012-04-06 17:25:08

回答

2

與ulmangt一樣,我建議您使用VBO,但在此之前,您只需計算可見面。

這可以通過(僅在開始時)檢查臉部是否與空體素(「空氣」)相鄰來輕鬆完成。如果是,請將該四邊形(面)添加到渲染中。

然後,你只是做這個檢查只對變化的體素的鄰居。例如:當用戶移除一個立方體時,檢查該體素的6個鄰居並將這些四邊形添加到渲染中。當體素被添加時做相反的操作,移除相鄰的四邊形。

有由體素的5×5×立方體

所以,相反的750輛四輪摩托車,你最終與視圖150

其他收益可以通過只繪製塊可以了(一組體素)(忽略的那些到玩家的後面)並使用距離限制。

通過使用八叉樹來渲染可能可見的塊,您可以變得更加瘋狂。

+0

謝謝:)現在,你有一個如何確定體素是否觸及體素的想法? – TheMorfeus 2012-04-12 14:16:11

+0

好吧,塊體素只是一個填充了體素類型的3d數組(我認爲我的世界使用一個字節來表示indev版本中的體素類型,現在不知道)。想到最簡單的方法就是遍歷整個數組,並檢查每個體素的鄰居並將可見四邊形添加到列表中。 (TL; DR:遍歷體素的三維陣列,忽略「空氣」類型的體素,檢查鄰居的空氣體素,添加可見的四邊形)。 – 2012-04-13 01:44:14

3

您的代碼有較大的性能問題。您不應該使用即時模式OpenGL渲染(glVertexXXX() calls)來繪製如此大量的頂點。

以這種方式執行渲染時,代碼必須調用每個頂點的圖形驅動程序,速度很慢。您可以使用Vertex Buffer Objects。這將允許您將所有的幾何圖形直接上傳到圖形卡上,然後用一個Java方法調用(可能是glDrawArrays)繪製所有的多維數據集。

+2

這只是解決了小問題。這裏的問題是他試圖以暴力的方式進行體素渲染,這沒有真正的工作機會。至少不適用於任何重要的輸入大小。 – pmr 2012-04-06 16:23:31

+0

我應該如何渲染它? – TheMorfeus 2012-04-07 08:07:41

1

一個好主意是不使用即時模式呈現您的塊,我使用顯示列表,因爲它們是最容易設置和非常快。其次,即使您仍然只使用即時模式,那麼在繪製時只使用一個glBegin/glEnd調用,將來會使用紋理圖集來表示紋理,以及您的主要問題是如何停止渲染不可見的表面。很簡單,我這樣做的方式基本上爲每個面返回一個布爾值的六個方法。如果該面的方向上的塊類型是空氣塊,則會簡單地返回,如果是。那意味着它將返回true,爲此將其渲染。並且在你的繪圖方法中添加參數「boolean backface,boolean topface ... etc」和一個if語句來檢查繪製哪一面。

希望我幫忙,祝你好運!

+0

這個問題已經超過2年了,我已經使用顯示列表解決了問題。儘管如此,我已經遠離這個項目。 – TheMorfeus 2014-08-27 12:01:17

+0

我沒有閱讀日期,但仍然會幫助尋找答案的人。 – ABOODYFJ 2014-08-31 07:34:16