2016-03-22 14 views
-1

Ich habe ein Programm, das sechs Felder auf dem Bildschirm zeichnet, die etwa 2000 Scheitelpunkte enthalten. Um die VBOs für diese zu erstellen, muss ich Pufferobjekte (Int/Float) verwenden. Ich muss in der Lage sein, die Scheitelpunkte usw. in einer XML-Datei zu speichern, so dass ich die Modellobjekte serialisieren, in B64 konvertieren und sie als Zeichenfolge speichern möchte. Problem ist, dass Pufferobjekte nicht serialisierbar sind.Warum starten statische Methoden beim Erstellen von VBOs Speicher?

Um dieses Problem zu umgehen, entfernte ich alle VBO-Code aus den Modellobjekten (es wurde ursprünglich aus einer separaten Klasse erweitert) und erstellte statische Methoden, um meine VBOs zu erstellen. Also rufe ich die statische Methode auf, um den VBO für ein Modell zu erstellen, und gebe dann die Handles zurück, damit ich Rendering, Update-Vertices usw. aufrufen kann. Dies hat jedoch den Effekt, dass der Speicher beim Erstellen der Modelle stark erhöht wird.

Warum sollte das sein? Ursprünglich war die Speichernutzung nicht einmal bemerkbar. Jetzt stürzt es die JVM ab. Ich habe keine der Code-Logik geändert, die Methoden sind die gleichen, nur jetzt sind sie statisch und geben die Handles zurück. Benutzen statische Methoden irgendwie mehr Speicher beim Erstellen von VBOs? Ich dachte, es wäre weniger? Ich lösche alle Puffer nach Gebrauch. Ich verfüge über alle ausgesuchten Modelle.

Edit: Hier ist die Render-Klasse, die die statischen Methoden enthält

package Drawing; 

import static org.lwjgl.opengl.GL11.GL_FLOAT; 
import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER; 
import static org.lwjgl.opengl.GL15.GL_DYNAMIC_DRAW; 
import static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER; 
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW; 
import static org.lwjgl.opengl.GL15.glBindBuffer; 
import static org.lwjgl.opengl.GL15.glBufferData; 
import static org.lwjgl.opengl.GL15.glBufferSubData; 
import static org.lwjgl.opengl.GL15.glGenBuffers; 
import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray; 
import static org.lwjgl.opengl.GL20.glVertexAttribPointer; 
import static org.lwjgl.opengl.GL30.glBindVertexArray; 
import static org.lwjgl.opengl.GL30.glGenVertexArrays; 

import java.nio.FloatBuffer; 
import java.nio.IntBuffer; 

import org.lwjgl.BufferUtils; 

/** 
* This class calls all vbo functions in a static way which allows me to 
* separate the Int/FloatBuffers from the model classes like Cube and 
* Quad. Int/FloatBuffers will not serialize so the Cube/Quad classes 
* cannot be saved to file. Keeping them static and separated 
* will overcome this problem. 
*/ 
public class Render { 

static int VERTEXCOUNT = 0;//((QUAD_SIZE * QUAD_SIZE) * 12); 
static FloatBuffer fbData = null;//BufferUtils.createFloatBuffer(VERTEXCOUNT); 
static FloatBuffer fbNorm = null;//BufferUtils.createFloatBuffer(VERTEXCOUNT); 
static FloatBuffer fbtex = null;//BufferUtils.createFloatBuffer((VERTEXCOUNT/12) * 8); 
static IntBuffer Indices = null; 
private static int _VAOHandle = 0; 
private static IntBuffer vboHandles; 

static final int POSITION_INDEX = 0; // index of vertex attribute "in_Position" 
static final int NORMALS_IDX = 1; 
static final int TEXTURE_IDX = 2; 
static final int IBO_IDX = 3; 

public static VBOIndexes createVBO(int QUAD_SIZE, 
     float[] vertBuffer, 
     float[] normals, 
     float[] UVs, 
     int[] idxBuffer) throws Exception { 

    VBOIndexes vboINDEXES = new VBOIndexes(); 

    try{ 

     VERTEXCOUNT = (int) ((QUAD_SIZE * QUAD_SIZE) * 12); 
     fbData = BufferUtils.createFloatBuffer(VERTEXCOUNT); 
     fbNorm = BufferUtils.createFloatBuffer(VERTEXCOUNT); 
     fbtex = BufferUtils.createFloatBuffer((VERTEXCOUNT/12) * 8); 
     Indices = BufferUtils.createIntBuffer(VERTEXCOUNT/2); 


     _VAOHandle = glGenVertexArrays(); 

     vboINDEXES.VAOHandle = _VAOHandle; 

     System.out.println("VAOHandle is : " + _VAOHandle); 

     glBindVertexArray(_VAOHandle); 

     vboHandles = BufferUtils.createIntBuffer(4); 
     glGenBuffers(vboHandles); 

     vboINDEXES.idxPOS = vboHandles.get(POSITION_INDEX); 
     vboINDEXES.idxNORM = vboHandles.get(NORMALS_IDX); 
     vboINDEXES.idxTEX = vboHandles.get(TEXTURE_IDX); 
     vboINDEXES.idxIBO = vboHandles.get(IBO_IDX); 

     //FloatBuffer fbData = BufferUtils.createFloatBuffer(vertBuffer.length); 
     fbData.put(vertBuffer); 
     fbData.rewind(); // rewind, otherwise LWJGL thinks our buffer is empty 

     glBindBuffer(GL_ARRAY_BUFFER, vboHandles.get(POSITION_INDEX)); 

     glBufferData(GL_ARRAY_BUFFER, fbData, GL_DYNAMIC_DRAW); 
     fbData.clear(); //don't need this anymore 


     //populate the normals buffer 
     //FloatBuffer fbNorm = BufferUtils.createFloatBuffer(normalsBuffer.length); 
     fbNorm.put(normals); 
     fbNorm.rewind(); 
     glBindBuffer(GL_ARRAY_BUFFER, vboHandles.get(NORMALS_IDX)); //the vertex data 
     glBufferData(GL_ARRAY_BUFFER, fbNorm, GL_STATIC_DRAW); 
     fbNorm.clear(); //don't need this anymore 

     //populate the texture buffer 

     fbtex.put(UVs); 
     fbtex.rewind(); 
     glBindBuffer(GL_ARRAY_BUFFER, vboHandles.get(TEXTURE_IDX)); 
     glBufferData(GL_ARRAY_BUFFER, fbtex, GL_DYNAMIC_DRAW); 
     fbtex.clear(); //don't need this anymore 

     Indices.put(idxBuffer); 
     Indices.rewind(); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboHandles.get(IBO_IDX)); 

     glBufferData(GL_ELEMENT_ARRAY_BUFFER, Indices, GL_STATIC_DRAW); 

     glEnableVertexAttribArray(POSITION_INDEX); 
     glEnableVertexAttribArray(NORMALS_IDX); 
     glEnableVertexAttribArray(TEXTURE_IDX); 

     glBindBuffer(GL_ARRAY_BUFFER, vboHandles.get(POSITION_INDEX)); 
     glVertexAttribPointer(0,3, GL_FLOAT, false,0,0);  

     //normals 
     glBindBuffer(GL_ARRAY_BUFFER, vboHandles.get(NORMALS_IDX)); 
     glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0); 

     glBindBuffer(GL_ARRAY_BUFFER, vboHandles.get(TEXTURE_IDX)); 
     glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, 0); 

     //bind IBO 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboHandles.get(IBO_IDX)); 

     glBindVertexArray(0); 

     glBindBuffer(GL_ARRAY_BUFFER, 0); 


     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 

     Indices.clear(); 

    }catch (Exception ex){ 
     System.out.println("createVBO: " + ex.getMessage()); 
     throw ex; 
    } 
    return vboINDEXES; 
} 

public static VBOIndexes createLineVBO(float[] vertBuffer, 
          int[] idxBuffer) throws Exception { 

    VBOIndexes vboINDEXES = new VBOIndexes(); 

    try{ 

     fbData = BufferUtils.createFloatBuffer(vertBuffer.length); 
     Indices = BufferUtils.createIntBuffer(vertBuffer.length/2); 

     _VAOHandle = glGenVertexArrays(); 

     vboINDEXES.VAOHandle = _VAOHandle; 

     glBindVertexArray(_VAOHandle); 

     vboHandles = BufferUtils.createIntBuffer(4); 
     glGenBuffers(vboHandles); 

     vboINDEXES.idxPOS = vboHandles.get(POSITION_INDEX); 
     vboINDEXES.idxIBO = vboHandles.get(IBO_IDX); 

     fbData.put(vertBuffer); 
     fbData.rewind(); // rewind, otherwise LWJGL thinks our buffer is empty 

     glBindBuffer(GL_ARRAY_BUFFER, vboHandles.get(POSITION_INDEX)); 

     glBufferData(GL_ARRAY_BUFFER, fbData, GL_STATIC_DRAW); 
     fbData.clear(); //don't need this anymore 

     //IntBuffer Indices = BufferUtils.createIntBuffer(idxBuffer.length); 
     Indices.put(idxBuffer); 
     Indices.rewind(); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboHandles.get(IBO_IDX)); 
     //Util.checkGLError(); 
     glBufferData(GL_ELEMENT_ARRAY_BUFFER, Indices, GL_STATIC_DRAW); 

     glEnableVertexAttribArray(POSITION_INDEX); 
     glBindBuffer(GL_ARRAY_BUFFER, vboHandles.get(POSITION_INDEX)); 
     glVertexAttribPointer(0,3, GL_FLOAT, false,0,0);  

     //bind IBO 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboHandles.get(IBO_IDX)); 

     Indices.clear(); 

     glBindVertexArray(0); 

     glBindBuffer(GL_ARRAY_BUFFER, 0); 
     //Util.checkGLError(); 

     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 

    }catch (Exception ex){ 
     System.out.println("createVBO: " + ex.getMessage()); 
     throw ex; 
    } 
    return vboINDEXES; 
} 

    public static void updateVertices(int offset, 
          float[] vertBuffer, 
          int idxPOS) 
    { 
     //populate the vertex buffer 
     FloatBuffer fbData = BufferUtils.createFloatBuffer(vertBuffer.length); 
     fbData.put(vertBuffer); 
     fbData.rewind(); 
     //glBindBuffer(GL_ARRAY_BUFFER, vboHandles.get(POSITION_INDEX)); //the vertex data 
     glBindBuffer(GL_ARRAY_BUFFER, idxPOS); 
     glBufferSubData(GL_ARRAY_BUFFER, offset, fbData); 
     fbData.clear(); //don't need this anymore 
    } 

    public static void updateNormals(int offset, 
           float[] normals, 
           int idxNORM) 
    { 

     //populate the vertex buffer 
     FloatBuffer fbData = BufferUtils.createFloatBuffer(normals.length); 
     fbData.put(normals); 
     fbData.rewind(); 
     //glBindBuffer(GL_ARRAY_BUFFER, vboHandles.get(NORMALS_IDX)); //the vertex data 
     glBindBuffer(GL_ARRAY_BUFFER, idxNORM); 
     glBufferSubData(GL_ARRAY_BUFFER, 0, fbData); 
     fbData.clear(); //don't need this anymore 
    } 

    public static void updateTexture(int offset, 
      float[] UVs, 
      int idxTEX) 
    { 

     //populate the texture buffer 
     FloatBuffer fbtex = BufferUtils.createFloatBuffer(UVs.length); 
     fbtex.put(UVs); 
     fbtex.rewind(); 

     //glBindBuffer(GL_ARRAY_BUFFER, vboHandles.get(TEXTURE_IDX)); //the texture data 
     glBindBuffer(GL_ARRAY_BUFFER, idxTEX); 
     glBufferSubData(GL_ARRAY_BUFFER, offset, fbtex); 
     fbtex.clear(); //don't need this anymore 
    } 

    public Render(){ 

    } 

} 

Die statischen Anrufe im Konstruktor der Felder (Array von Fliesen-Objekte) werden wie folgt hergestellt:

public Quad(Map<Integer, Cube> c, int SIZE) throws Exception{ 
//public Quad(ArrayList<Cube> c, int SIZE) throws Exception{ 
    QUAD_SIZE = SIZE; 
    initArrays(); 
    initVBOData(SIZE); 
    createVBO(); 
    cubes = c; 

} 
+0

Haben Sie wirklich brauchen, Positionen in Ebene xml? Sind Metadaten in XML und Positionen in Binärdateien eine Option für Sie? – elect

+0

Dieser Teil ist nicht wirklich das Problem. Ich speichere nicht wirklich alle Eckenpositionen, nur Höhen und andere Eigenschaften der Modelle. Das Problem ist, dass durch den Aufruf dieser statischen Methoden der Speicher einfach abstürzt. Was einst knapp 100k war, ist jetzt über 1G ?? Und die Logik wurde nicht geändert. –

+0

Ein paar tausend Vertices sind wirklich eine kleine Menge, überprüfen Sie Ihren Code, denn ich denke, Sie machen etwas falsch. Wenn Sie etwas von Ihrem Code veröffentlichen können. – elect

Antwort

0

Ich glaube, die Antwort ist, dass statische Klassen GC nicht bieten. Mit all den Daten, die beim Erstellen von VBOs herumgereicht werden, beginnt sich das G wirklich zu stauen ...

+0

genau richtig. statische Klassen sind meines Wissens Zuteilungen für die Dauer des Programms. Sie bewegen sich nicht, sie sammeln keinen Müll, sie sitzen nur da und warten auf Anrufung. – sova

+0

Genau * falsch *. Die Lebensdauer eines Objekts hat nichts damit zu tun, ob seine Klasse "statisch" ist. @sova – EJP

+0

@EJP, nun, ich bin immer noch ein Neuling, also okay, aber was ist mit statischen finalen Objekten? – sova

0

Ihr Code sieht sehr verwirrend aus, Sie sollten etwas Zeit damit verbringen, besser zu verstehen, wie OpenGL funktioniert und es sauberer und lesbarer macht . Ich würde vorschlagen, dass Sie Inspiration von this sample nehmen.

paar Überlegungen:

  • Sie nicht statisch müssen bei allen
  • Ich weiß nicht, lwjgl, aber ich denke, es direkte Puffer benötigt und Sie haben keine Garantie, dass sie durch entfernt werden werden der Müllsammler, also sollten Sie sie selbst zuordnen und frei machen, wenn Sie sie nicht mehr brauchen. Ich habe eine kleine Klasse erstellt, um direkte Puffer freizugeben, die aus JM3 here
  • Redundanz durch Speichern der OpenGL-Ressourcen-Namen in vboINDEXES übernommen wurden.Sie verwenden bereits vboHandles direkt
  • , wenn die Dimension Ihrer Puffer nicht ändert, ordnen sie einmal und halten sie (fbData, fbNorm, fbTex), brauchen nicht zu clear() sie zu
  • aus diesem Grund, wenn Sie updateNormals() Sie einen neuen Puffer nicht instanziiert, verwenden Sie die man schon bei der
  • durch eine logische Sicht beginnen instanziiert, IBO_INDEX sollte nicht Teil der vboINDEXES
  • sein, wenn Sie die Variable Halte glVertexAttribPointer Pass als erstes Argument nennen der Attributindex, z. B. POSITION_INDEX

ps: der Plural von Index Indizes