2012-04-06 7 views
2

Ich mache ein Voxel-basiertes Spiel, und für die Bedürfnisse davon erstelle ich eine Block-Rendering-Engine.Wie höre ich auf, unsichtbare Gesichter zu rendern?

Punkt ist, dass ich viele Würfel erzeugen muss. Jedes Mal, wenn ich mehr als 16x16x16 Blöcke dieser Blöcke rendere, wird mein FPS kaum fallen gelassen, weil es alle 6 Gesichter aller dieser Würfel würfelt. Das sind 24 576 Quads, und das will ich nicht.

Also, meine Frage ist, Wie zu stoppen, Rendering Vertices (oder Quads), die nicht sichtbar sind, und damit die Leistung meines Spiels zu erhöhen?

Hier ist die Klasse für einen Block Rendering:

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");} 
} 

Hier ist Code, den sie macht:

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

Jeder wird helfen? – TheMorfeus

+0

mögliches Duplikat von [Wie entferne ich das Gesicht in einer Würfel-Welteinheit?} (Http://stackoverflow.com/questions/6319655/how-to-do-face-removal-in-a-unit- cube-world-a-la-minecraft) –

Antwort

2

Ich empfehle, wie Ulmangt gesagt, dass Sie VBO verwenden, aber vorher müssen Sie nur die sichtbaren Flächen berechnen.

Dies kann leicht durch (nur einmal am Anfang) überprüft werden, ob ein Gesicht Nachbar eines leeren Voxel ("Luft") ist. Wenn dies der Fall ist, füge das Quad (Gesicht) dem Rendering hinzu.

Danach überprüfen Sie nur die Nachbarn der geänderten Voxel. Beispiel: Wenn der Benutzer einen Würfel entfernt, überprüfen Sie die 6 Nachbarn dieses Voxels und fügen Sie diese Quadrate dem Rendering hinzu. Tun Sie das Gegenteil, wenn Voxel hinzugefügt werden, entfernen Sie benachbarte Quads.

So mit einem 5x5x5-Würfel von Voxel gemacht, statt 750 Quads, am Ende mit 150

Anderen Gewinnen können nur durch Rendering-Stücke (eine Gruppe von Voxel) in der Ansicht (ohne Berücksichtigung diejenigen, haben seine auf der Rückseite des Spielers) und mit einem Distanzlimit.

Sie können sogar noch verrückter gehen, indem Sie Octrees verwenden, um nur Stücke zu rendern, von denen Sie wissen, dass sie möglicherweise sichtbar sind.

+0

Danke :) Nun, hast du eine Idee, wie man erkennt, ob Voxel Voxel berührt? – TheMorfeus

+0

Nun, ein Brocken Voxel wird nur ein 3D-Array mit dem Typ von Voxel gefüllt sein (ich denke, dass Minecraft ein Byte verwendet, um den Voxel-Typ in den Indev-Versionen darzustellen, keine Ahnung.). Der einfachste Weg, der Ihnen einfällt, besteht darin, einfach durch das gesamte Array zu iterieren und die Nachbarn jedes Voxels zu prüfen und die sichtbaren Quads zu einer Liste hinzuzufügen. (TL; DR: Iterate durch 3D-Array von Voxeln, Ignorieren "Luft" Typ Voxel, überprüfen Nachbarn für Luft Voxel, fügen Sie sichtbare Quads.) –

3

Ihr Code hat ein größeres Performance-Problem. Sie sollten nicht OpenGL-Rendering im unmittelbaren Modus (glVertexXXX() calls) verwenden, um eine so große Anzahl von Vertices zu zeichnen.

Wenn Sie das Rendern auf diese Weise durchführen, muss Ihr Code einen Grafiktreiber für jeden Vertex aufrufen, was langsam ist.

Stattdessen sollten Sie Vertex Buffer Objects verwenden. Dadurch können Sie Ihre gesamte Geometrie direkt auf die Grafikkarte hochladen und dann alle Ihre Cubes in einem einzigen Java-Methodenaufruf zeichnen (wahrscheinlich glDrawArrays).

+2

Das behebt nur das kleinere Problem. Das Problem hier ist, dass er versucht, Voxel-Rendering in einer brutalen Kraft zu machen, die keine echte Chance hat, zu arbeiten. Zumindest nicht für irgendeine Eingabegröße, die zählt. – pmr

+0

Wie soll ich es dann rendern? – TheMorfeus

1

Eine gute Idee ist es, NICHT den unmittelbaren Modus zu verwenden, um Ihre Blöcke zu rendern, ich verwende Display-Listen, weil sie am einfachsten einzurichten sind und sehr schnell sind. Zweitens, auch wenn Sie immer noch nur den Sofort-Modus verwenden, dann verwenden Sie nur einen glBegin/glEnd-Aufruf, wenn Sie zeichnen, verwenden Sie einen Textur-Atlas für Texturen in der Zukunft und zu Ihrer Hauptfrage, wie Sie aufhören, unsichtbare Gesichter zu Rendern ist ziemlich einfach, Die Art, wie ich es mache, ist grundsätzlich sechs Methoden für jedes Gesicht, die einen Boolean zurückgibt. Sie würden einfach zurückkehren, wenn der Blocktyp in der Richtung dieses Gesichts ein Luftblock ist, wenn es ist. Dann heißt das, dass es wahr wird, deshalb render es. Und in Ihrer Zeichenmethode fügen Sie die Parameter "boolean backface, boolean topface ... etc" und eine if-Anweisung hinzu, die überprüft, welche Seite gezeichnet werden soll.

hoffe, ich habe geholfen, Viel Glück!

+0

Diese Frage ist über 2 Jahre alt, und ich bereits das Problem mit Display-Listen gelöst. Trotzdem bin ich schon von diesem Projekt abgekommen. – TheMorfeus

+0

Ich habe das Datum nicht gelesen, wäre aber immer noch eine Hilfe für Leute, die nach Antworten suchen. – ABOODYFJ

Verwandte Themen