我有一个程序在屏幕上绘制六个字段,每个字段包含大约2000个顶点。要为这些创建VBO,我需要使用Buffer对象(Int / Float)。我需要能够将顶点位置等保存到xml文件中,所以我想序列化模型对象,转换为B64并将它们保存为字符串。问题是缓冲区对象不可序列化。
因此,为了解决这个问题,我从模型对象中删除了所有VBO代码(它最初是从一个单独的类扩展而来的),并创建了静态方法来创建我的VBO。因此,我调用静态方法为模型创建VBO,然后返回句柄,以便我可以调用渲染,更新顶点等。但是,这会产生在创建模型时严重增加内存的效果。
为什么会这样?最初内存使用量甚至都不明显。现在它崩溃了JVM。我没有改变任何代码逻辑,方法是相同的,除了现在它们是静态的并传回句柄。在创建VBO时,静态方法是否会以某种方式使用更多内存?我以为会少一点?我在使用后清除所有缓冲液。我处理了所有淘汰的模型。
修改 这是包含静态方法的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(){
}
}
静态调用是在字段的构造函数(tile对象数组)中进行的,如下所示:
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 :(得分:0)
我相信答案是静态类不提供GC。随着所有数据传递创建VBO,G真的开始堆积......
答案 1 :(得分:0)
您的代码看起来很混乱,您应该花一些时间来更好地了解OpenGL的工作原理,使其更清晰,更易读。 我建议你从this sample中获取灵感。
很少考虑:
vboINDEXES
内保存opengl资源名称来避免冗余。您已经直接使用vboHandles
fbData
,fbNorm
,fbTex
),不需要{ {1}}他们也是clear()
未实例化新缓冲区时,请使用已在开始时实例化的缓冲区updateNormals()
不应该是IBO_INDEX
vboINDEXES
作为第一个参数传递包含属性索引的变量时,例如glVertexAttribPointer
ps:索引的复数是 indices