2016-03-22 23 views
-1

Ekranda yaklaşık 2000 köşe içeren altı alan çizen bir programım var. Bunlar için VBO'ları oluşturmak için Tampon nesnelerini kullanmalıyım (Int/Float). Ben verteks pozisyonları bir xml dosyasına kaydedebilmem gerekir, bu yüzden model nesnelerini serileştirmek, B64'e dönüştürmek ve bir ip olarak kaydetmek istiyorum. Sorun, Tampon nesneleri serileştirilemez.VBO'lar oluştururken neden statik yöntemler bellek kullanıyor?

Bu soruna geçici bir çözüm bulmak için tüm VBO kodlarını model nesnelerinden kaldırdım (orijinal olarak ayrı bir sınıftan genişletildim) ve VBO'larım oluşturmak için statik yöntemler oluşturdum. Yani, bir model için VBO oluşturmak için statik yöntemini çağırıyorum ve daha sonra tanıtıcıları çağırmak, başlıkları güncellemek vb. Için tanıtıcıları döndürüyorum. Ancak, bu, modeller oluşturulduğunda belleğin ciddi şekilde artmasına neden oldu.

Neden böyle olur? Başlangıçta bellek kullanımı bile fark edilmedi. Şimdi JVM'yi çökertti. Hiçbir kod mantığını değiştirmedim, yöntemler şu anda aynıdır, bunlar statiktir ve kolları geri döndürürler. VBO'lar oluştururken statik yöntemler bir şekilde daha fazla bellek kullanıyor mu? Daha az olacağını düşündüm? Kullandıktan sonra tüm tamponları temizliyorum. İtlaf edilen tüm modelleri elden çıkardım.

Düzenleme: İşte

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(){ 

    } 

} 

statik çağrılar gibi alanlarda (kiremit nesneleri dizisi) arasında yapıcı yapılır statik yöntemleri içeren Render sınıf izler geçerli:

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

gerçekten düz xml pozisyonları mi istiyorsunuz nedir? Meta veriler xml'de ve ikili konumlarda sizin için bir seçenek midir? – elect

+0

Bu bölüm gerçekten sorun değil. Aslında tüm verteks konumlarını, sadece yüksekliklerini ve modellerin diğer özelliklerini kaydetmiyorum. Sorun şu ki, bu statik yöntemleri çağırarak bellek sadece öldürüyor. Bir zamanlar sadece 100k olan şimdi 1G'nin üzerinde miydi? Ve mantık değişmedi. –

+0

Bin köşe bir çift gerçekten küçük bir miktar, çift kodunuzu kontrol edin, çünkü yanlış bir şey yapıyorsunuz sanırım. Kodunuzun bir kısmını gönderebilirseniz .. – elect

cevap

0

Cevabın statik sınıflar GC sağlamaz oluşuna bağlıyor. VBO'lar yaratma etrafında aktarılan tüm verilerle, G gerçekten yığılmaya başlar ...

+0

kesinlikle doğru. Statik sınıflar, benim bilgime, programın süresi için tahsislerdir. Hareket etmiyorlar, topladıkları çöpleri almıyorlar, sadece orada bekleyenleri çağırıyorlar. – sova

+0

Kesinlikle * yanlış *. Bir nesnenin ömrünün, sınıfının "statik" olup olmadığıyla tam olarak bir ilgisi yoktur. @sova – EJP

+0

@EJP, ben hala bir acemi, tamam, ama ne statik final nesneleri hakkında? – sova

0

Kodunuz çok kafa karıştırıcı görünüyor, OpenGL'nin nasıl çalıştığını daha iyi anlamak ve daha okunabilir hale getirmek için biraz zaman harcamalısınız. . this sample'dan ilham almanızı öneririm.

Birkaç hususlar:

  • ben lwjgl bilmediğim her
  • de statik gerekmez, ama doğrudan tamponlarını ihtiyacı tahmin ve onlar tarafından kaldırılmış olacak garantiniz yok Çöp toplayıcı, böylece onları kendiniz ayırmanız ve artık ihtiyacınız olmadığında onları serbest bırakmanız gerekir. Ben vboINDEXES içeride opengl kaynaklar isimleri kaydederek önlemek fazlalık
  • JM3 here alınan direkt tamponlarını, ayırması için küçük bir sınıf yarattı.Zaten çok clear() bu nedenle
  • onlara ihtiyacım yok, senin tamponların boyutu değişmezse, (fbData, fbNorm, fbTex) bir zamanlar onları ayırmak ve onları tutmak doğrudan vboHandles
  • kullanırken, zaman ilk argüman değişken tutma olarak glVertexAttribPointer geçiş çağırdığınızda, yeni bir tampon örneğini zaten bir görüş mantık puan
  • başlayacak de başlatılamaz birini kullanmayan updateNormals(), IBO_INDEXvboINDEXES
  • parçası olmamalıgibi özellik dizini

ps: endeksinin çoğul endeksleri

İlgili konular