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;
}
Haben Sie wirklich brauchen, Positionen in Ebene xml? Sind Metadaten in XML und Positionen in Binärdateien eine Option für Sie? – elect
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. –
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