[英]Why do static methods run up memory when creating VBO's?
I have a program that draws six fields on screen that contain around 2000 vertices per.我有一个程序在屏幕上绘制六个字段,每个字段包含大约 2000 个顶点。 To create the VBOs for these I need to use Buffer objects (Int/Float).要为这些创建 VBO,我需要使用 Buffer 对象(Int/Float)。 I need to be able to save the vertex positions etc to an xml file so I want serialize the model objects, convert to B64 and save them as a string.我需要能够将顶点位置等保存到 xml 文件中,所以我想序列化模型对象,转换为 B64 并将它们保存为字符串。 Problem is Buffer objects are not serializable.问题是 Buffer 对象不可序列化。
So, to get around this problem I removed all VBO code from the model objects (it was originally extended from a separate class) and created static methods to create my VBOs.因此,为了解决这个问题,我从模型对象中删除了所有 VBO 代码(它最初是从一个单独的类扩展而来)并创建了静态方法来创建我的 VBO。 So, I call the static method to create the VBO for a model and then return the handles so I can call render, update vertices etc. This, however, has had the effect of seriously ramping up memory when the models are created.因此,我调用静态方法为模型创建 VBO,然后返回句柄,以便我可以调用渲染、更新顶点等。但是,这会在创建模型时严重增加内存。
Why would this be?为什么会这样? Originally the memory usage was not even noticeable.最初的内存使用甚至不明显。 Now it crashes the JVM.现在它使 JVM 崩溃。 I haven't changed any of the code logic, the methods are the same except now they are static and pass back the handles.我没有更改任何代码逻辑,方法是相同的,除了现在它们是静态的并传回句柄。 Do static methods somehow use more memory when creating VBO's?创建 VBO 时,静态方法是否会以某种方式使用更多内存? I thought it would be less?我还以为会少呢? I do clear all buffers after use.使用后我会清除所有缓冲区。 I do dispose of all culled models.我确实处理了所有剔除的模型。
Edit: Here is the Render class that contains the static methods编辑:这是包含静态方法的 Render 类
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(){
}
}
The static calls are made in the constructor of the fields (array of tile objects) as follows:静态调用在字段(平铺对象数组)的构造函数中进行,如下所示:
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;
}
I believe the answer is that static classes do not provide GC.我相信答案是静态类不提供 GC。 With all of the data being passed around creating VBOs the G really starts to pile up...随着所有数据被传递创建 VBO,G 真的开始堆积起来......
Your code looks very confusing, you should spend some time in order to better understand how OpenGL works and make it cleaner and more readable.您的代码看起来很混乱,您应该花一些时间来更好地理解 OpenGL 的工作原理并使其更清晰、更具可读性。 I'd suggest you to take inspiration from this sample .我建议你从这个样本中获得灵感。
Few considerations:几点考虑:
vboINDEXES
.通过在vboINDEXES
保存 opengl 资源名称来避免冗余。 You are already using vboHandles
directly您已经vboHandles
直接使用vboHandles
fbData
, fbNorm
, fbTex
), don't need to clear()
them too如果缓冲区的维度没有改变,分配一次并保留它们( fbData
、 fbNorm
、 fbTex
),也不需要clear()
它们updateNormals()
don't instantiate a new buffer, use the one already instantiated at the begin因此,当您updateNormals()
不实例化新缓冲区时,请使用在开始时已实例化的缓冲区IBO_INDEX
should not be part of the vboINDEXES
从逻辑的角度来看, IBO_INDEX
不应该是vboINDEXES
一部分glVertexAttribPointer
pass as first argument the variable holding the attribute index, such as POSITION_INDEX
当您调用glVertexAttribPointer
将保存属性索引的变量作为第一个参数传递,例如POSITION_INDEX
ps: the plural of index is indices ps:index的复数是indexes
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.