2016-03-29 8 views
0

私はそのクラスに「RectManager」というコードダンプがあります。私の問題は奇妙なOpenGLの問題です。私はlwjgl 2.9.3を使用しています。私のグラフィックスカードでは、VBOあたりの頂点の制限は33000です。LWJGL 2.9.3、VAOごとに複数のVBOを描画することができない

私のクラスは四角形のグループを一連の長方形に単純化し、そのデータをVBOにバッファして要求に応じて描画します。

ここで問題になるのは、複数の異なるメッシュを描画するために複数のRectManagerインスタンスをグループ化することです。ただし、RectManagerのインスタンスごとに異なるVAOを指定しないと、最初のインスタンスだけが描画されます。なぜ私は分かりません。 この問題に対するいかなる扇動も大歓迎です。

両方の例では、複数のRectManagerインスタンス(正確には6)があることに注意してください。私は別のVAOの

ソース

protected class RectManager { 
    Vector loopVec = new Vector(Chunk.chunkSize,Chunk.chunkSize,Chunk.chunkDepth); 
    ArrayList<RecDim> rectArray = new ArrayList<RecDim>(); 

    int[] vboOffsets; 
    int[] vboSizes; 
    int vboSizeTotal = 0; 
    int vboSizeReal = 0; 
    int vboOffset = 0; 
    int objectID; 
    int bufferID; 

    int indexX,indexY,indexZ; 
    int bitwise = 0; 
    int arrayID; 

    boolean isStarted = false; 
    int startC = 0; 
    int startU = 0; 
    int maxC = 1000; 

    Direction dir; 

    public RectManager(Direction depthDir,int arrID){ 
     dir = depthDir; 

     Vector indexVec = new Vector(1,Chunk.chunkSize,Chunk.chunkSizeSq); 

     if(depthDir.getPure() == Direction.NORTH){//Y+ 
      indexVec.rollRight(); 
      loopVec.rollRight(); 

      if(depthDir.isPure){ 
       bitwise = 2048; 
      }else{ 
       bitwise = 1024; 
      } 
     }else if(depthDir.getPure() == Direction.EAST){//X+ 
      indexVec.rollLeft(); 
      loopVec.rollLeft(); 

      if(depthDir.isPure){ 
       bitwise = 4096; 
      }else{ 
       bitwise = 8192; 
      } 
     }else{ 
      if(depthDir.isPure){ 
       bitwise = 32768; 
      }else{ 
       bitwise = 16384; 
      } 
     } 

     indexX = (int)indexVec.X; 
     indexY = (int)indexVec.Y; 
     indexZ = (int)indexVec.Z; 

     vboOffsets = new int[(int)loopVec.Z]; 
     vboSizes = new int[(int)loopVec.Z]; 


     arrayID = arrID; 
     objectID = GL15.glGenBuffers(); 
     bufferID = GL15.glGenBuffers(); 

     GL30.glBindVertexArray(arrayID); 
     GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,bufferID); 
     GL15.glBufferData(GL15.GL_ARRAY_BUFFER,Chunk.chunkSizeSq*6*Vertex.BYTES,GL15.GL_STATIC_DRAW); 


     GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,objectID); 

     int defaultRectCount = 2000; 
     vboSizeTotal = defaultRectCount*6*Vertex.BYTES+1; 

     GL15.glBufferData(GL15.GL_ARRAY_BUFFER,vboSizeTotal,GL15.GL_STATIC_DRAW); 

     GL20.glVertexAttribPointer(0,3,GL11.GL_FLOAT,false,Vertex.BYTES,0); 
     GL20.glVertexAttribPointer(1,4,GL11.GL_FLOAT,false,Vertex.BYTES,Vertex.COLOR_OFFSET); 
     GL20.glVertexAttribPointer(2,2,GL11.GL_FLOAT,false,Vertex.BYTES,Vertex.UV_OFFSET); 

     Vertex vert = new Vertex(0,0,0); 
     int depth = 0; 

     FloatBuffer buff = GL30.glMapBufferRange(GL15.GL_ARRAY_BUFFER,0,vboSizeTotal,GL30.GL_MAP_WRITE_BIT,null).asFloatBuffer(); 

     Color c = new Color(); 
     c.setColorHSB((float)dir.ordinal()/6,1,1); 
     vert.setColor(c.r,c.g,c.b); 
     depth += (float)dir.ordinal()/6; 

     for(int i=0; i<Chunk.chunkDepth; i++){ 
      vert.set(-0.5f,0.5f, 0.5f + depth).addToBuffer(buff); 
      vert.set(-0.5f,-0.5f, 0.5f + depth).addToBuffer(buff); 
      vert.set(0.5f,0.5f, 0.5f + depth).addToBuffer(buff); 


      vert.set(-0.5f,-0.5f, 0.5f + depth).addToBuffer(buff); 
      vert.set(0.5f,0.5f, 0.5f + depth).addToBuffer(buff); 
      vert.set(0.5f,-0.5f, 0.5f + depth).addToBuffer(buff); 
      depth++; 
     } 

     GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER); 
     GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,0); 
     GL30.glBindVertexArray(0); 
    } 

    public void render(){ 
     GL11.glDrawArrays(GL11.GL_TRIANGLES,0,vboSizeReal/Vertex.BYTES); 
    } 

    private void updateVBO(int depth){ 
     int vboSize = vboSizes[depth]*Vertex.BYTES; 
     int len = rectArray.size(); 
     int bytes = len*6*Vertex.BYTES; 
     int offset = vboOffsets[depth]; 

     GL30.glBindVertexArray(arrayID); 
     GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,objectID); 

     if(vboSize != bytes){ 
      //System.out.println("Pre "+vboSizeReal+","+vboSize+","+bytes); 
      vboSizeReal = (vboSizeReal-vboSize)+bytes; 
      vboSizes[depth] = len*6; 

      //System.out.println("Resize! "+(vboSize-bytes)+" "+vboSize+" "+bytes+"\t\t"+vboSizeReal); 


      if(vboSizeReal > vboSizeTotal){ 
       throw new RuntimeException("FUCK Out of Space VBO "+vboSizeReal+","+vboSizeTotal); 
      } 

      if(vboSize == 0){ 
       offset = vboOffset; 
       vboOffsets[depth] = vboOffset; 
       vboOffset += bytes; 
      }else{ 
       int nextOffset = Integer.MAX_VALUE; 
       int oSet; 
       int id = 0; 
       int dif = vboSize-bytes; 

       for(int i=0; i<vboOffsets.length; i++){ 
        oSet = vboOffsets[i]; 

        if(oSet < nextOffset && oSet > offset){ 
         nextOffset = oSet; 
         id = i; 
        } 
       } 

       if(id == 0){//Shrink Buffer Instead 
        //vboOffset = offset+bytes; 
        vboOffset -= dif;//Its Positive 
       }else{ 
        int size = vboSizes[id]*Vertex.BYTES; 

        GL15.glBindBuffer(GL31.GL_COPY_WRITE_BUFFER,bufferID); 

        GL31.glCopyBufferSubData(GL15.GL_ARRAY_BUFFER,GL31.GL_COPY_WRITE_BUFFER,nextOffset,0,size); 
        GL31.glCopyBufferSubData(GL31.GL_COPY_WRITE_BUFFER,GL15.GL_ARRAY_BUFFER,0,offset+bytes,size); 

        GL15.glBindBuffer(GL31.GL_COPY_WRITE_BUFFER,0); 

        for(int i=0; i<vboOffsets.length; i++){ 
         oSet = vboOffsets[i]; 

         if(oSet > offset){ 
          vboOffsets[i] = oSet-dif; 
         } 
        } 
       } 
      } 

      vboSize = bytes; 
     }else{ 
      //System.out.println("Non-Resize"); 
     } 


     if(len == 0){ 
      GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,0); 
      GL30.glBindVertexArray(0); 
      return; 
     } 


     GL20.glVertexAttribPointer(0,3,GL11.GL_FLOAT,false,Vertex.BYTES,0); 
     GL20.glVertexAttribPointer(1,4,GL11.GL_FLOAT,false,Vertex.BYTES,Vertex.COLOR_OFFSET); 
     GL20.glVertexAttribPointer(2,2,GL11.GL_FLOAT,false,Vertex.BYTES,Vertex.UV_OFFSET); 

     FloatBuffer buff = GL30.glMapBufferRange(GL15.GL_ARRAY_BUFFER,offset,vboSize,GL30.GL_MAP_WRITE_BIT | GL30.GL_MAP_UNSYNCHRONIZED_BIT,null).asFloatBuffer(); 

     int sizeC,sizeU; 
     Vertex vert = new Vertex(0,0,0); 
     Color c = new Color(); 
     c.setColorHSB((float)depth/loopVec.Z,1,1); 
     vert.setColor(c.r,c.g,c.b); 
     //float count = 0; 

     //System.out.println(dir+" "+(len > 0 ? rectArray.get(0) : "?")+" "+depth+" "+loopVec); 
     Vector vec = new Vector(); 

     for(RecDim rect : rectArray){ 
      sizeC = rect.x2-rect.x; 
      sizeU = rect.y2-rect.y; 

      //c.setColorHSB(count++/(rectArray.size()+1),1,1); 
      //vert.setColor(c.r,c.g,c.b); 


      if(dir == Direction.UP){ 
       vert.set(-0.5f + rect.x,0.5f + rect.y2, 0.5f + depth).setUV(0,0).addToBuffer(buff); 
       vert.set(-0.5f + rect.x,-0.5f + rect.y, 0.5f + depth).setUV(0,sizeU).addToBuffer(buff); 
       vert.set(0.5f + rect.x2,0.5f + rect.y2, 0.5f + depth).setUV(sizeC,0).addToBuffer(buff); 

       vert.set(0.5f + rect.x2,0.5f + rect.y2, 0.5f + depth).setUV(sizeC,0).addToBuffer(buff); 
       vert.set(-0.5f + rect.x,-0.5f + rect.y, 0.5f + depth).setUV(0,sizeU).addToBuffer(buff); 
       vert.set(0.5f + rect.x2,-0.5f + rect.y, 0.5f + depth).setUV(sizeC,sizeU).addToBuffer(buff); 
      }else if(dir == Direction.DOWN){ 
       vert.set(0.5f + rect.x2,0.5f + rect.y2,-0.5f + depth).addToBuffer(buff); 
       vert.set(0.5f + rect.x2,-0.5f + rect.y,-0.5f + depth).addToBuffer(buff); 
       vert.set(-0.5f + rect.x,0.5f + rect.y2,-0.5f + depth).addToBuffer(buff); 

       vert.set(-0.5f + rect.x,0.5f + rect.y2,-0.5f + depth).addToBuffer(buff); 
       vert.set(0.5f + rect.x2,-0.5f + rect.y,-0.5f + depth).addToBuffer(buff); 
       vert.set(-0.5f + rect.x,-0.5f + rect.y,-0.5f + depth).addToBuffer(buff); 
      }else if(dir == Direction.EAST){ 
       vert.set(0.5f + depth,-0.5f + rect.x,0.5f + rect.y2).addToBuffer(buff); 
       vert.set(0.5f + depth,0.5f + rect.x2,-0.5f + rect.y).addToBuffer(buff); 
       vert.set(0.5f + depth,0.5f + rect.x2,0.5f + rect.y2).addToBuffer(buff); 

       vert.set(0.5f + depth,-0.5f + rect.x,-0.5f + rect.y).addToBuffer(buff); 
       vert.set(0.5f + depth,0.5f + rect.x2,-0.5f + rect.y).addToBuffer(buff); 
       vert.set(0.5f + depth,-0.5f + rect.x,0.5f + rect.y2).addToBuffer(buff); 
      }else if(dir == Direction.WEST){ 
       vert.set(-0.5f + depth,0.5f + rect.x2,0.5f + rect.y2).addToBuffer(buff); 
       vert.set(-0.5f + depth,0.5f + rect.x2,-0.5f + rect.y).addToBuffer(buff); 
       vert.set(-0.5f + depth,-0.5f + rect.x,0.5f + rect.y2).addToBuffer(buff); 

       vert.set(-0.5f + depth,-0.5f + rect.x,0.5f + rect.y2).addToBuffer(buff); 
       vert.set(-0.5f + depth,0.5f + rect.x2,-0.5f + rect.y).addToBuffer(buff); 
       vert.set(-0.5f + depth,-0.5f + rect.x,-0.5f + rect.y).addToBuffer(buff); 
      }else if(dir == Direction.NORTH){ 
       vert.set(0.5f + rect.y2,0.5f + depth,0.5f + rect.x2).addToBuffer(buff); 
       vert.set(0.5f + rect.y2,0.5f + depth,-0.5f + rect.x).addToBuffer(buff); 
       vert.set(-0.5f + rect.y,0.5f + depth,0.5f + rect.x2).addToBuffer(buff); 

       vert.set(-0.5f + rect.y,0.5f + depth,0.5f + rect.x2).addToBuffer(buff); 
       vert.set(0.5f + rect.y2,0.5f + depth,-0.5f + rect.x).addToBuffer(buff); 
       vert.set(-0.5f + rect.y,0.5f + depth,-0.5f + rect.x).addToBuffer(buff); 

      }else{//SOUTH 
       vert.set(-0.5f + rect.y,-0.5f + depth,0.5f + rect.x2).addToBuffer(buff); 
       vert.set(0.5f + rect.y2,-0.5f + depth,-0.5f + rect.x).addToBuffer(buff); 
       vert.set(0.5f + rect.y2,-0.5f + depth,0.5f + rect.x2).addToBuffer(buff); 

       vert.set(-0.5f + rect.y,-0.5f + depth,-0.5f + rect.x).addToBuffer(buff); 
       vert.set(0.5f + rect.y2,-0.5f + depth,-0.5f + rect.x).addToBuffer(buff); 
       vert.set(-0.5f + rect.y,-0.5f + depth,0.5f + rect.x2).addToBuffer(buff); 

      } 
     } 

     GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER); 
     GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,0); 
     GL30.glBindVertexArray(0); 
    } 

    public void calcAll(){ 
     for(int d=0; d<loopVec.Z; d++){ 
      isStarted = false; 
      maxC = 1000; 

      calcLayerInternal(d); 

      if(isStarted){ 
       rectArray.add(new RecDim(startC,startU,maxC,(int)loopVec.Y-1)); 

       d--; 
       continue; 
      } 

      updateVBO(d); 
      rectArray.clear(); 
     } 

     rectArray.clear(); 
    } 

    public void calcLayer(int d){ 
     rectArray.clear(); 

     while(true) { 
      isStarted = false; 
      maxC = 1000; 

      calcLayerInternal(d); 

      if(!isStarted){ 
       break; 
      } 

      rectArray.add(new RecDim(startC,startU,maxC,(int)loopVec.Y-1)); 
     } 

     updateVBO(d); 

    } 

    private void calcLayerInternal(int d){ 
     int index; 
     Block b; 

     for(int u=0; u<loopVec.Y; u++){ 
      for(int c=0; c<loopVec.X; c++){ 
       if(isStarted){ 
        if(c > maxC){ 
         break; 
        } 

        if(c < startC){ 
         c = startC; 
        } 
       }else if(inRect(c,u,rectArray)){ 
        continue; 
       } 


       index = d*indexZ + u*indexY + c*indexX; 
       b = Blocks.getBlockByID(owner.blocks[index]); 

       if(b.isAir() || inRect(c,u,rectArray) || (owner.metaData[index] & bitwise) == 0){ 
        if(isStarted){ 
         if(maxC != 1000){ 
          rectArray.add(new RecDim(startC,startU,maxC,u-1)); 
          u = 0; 

          isStarted = false; 
          maxC = 1000; 

          break; 
         }else{ 
          maxC = c-1; 
          break; 
         } 
        } 
       }else if(!isStarted){ 
        isStarted = true; 
        startC = c; 
        startU = u; 
       } 
      } 

      if(isStarted && maxC == 1000){ 
       maxC = (int)loopVec.X-1; 
      } 
     } 
    } 
} 

編集

を使用する場合

私は同じVAO

を使用3210

public class Vertex { 
    public static int SIZE = 9; 
    public static int BYTES = Float.BYTES * 9; 
    public static int POSITION_OFFSET = 0; 
    public static int COLOR_OFFSET = Float.BYTES * 3; 
    public static int UV_OFFSET = Float.BYTES * 7; 

    float[] data = new float[SIZE]; 

    protected Vertex(float X,float Y,float Z){ 
     data[0] = X; 
     data[1] = Y; 
     data[2] = Z; 
     data[3] = 1f; 
     data[4] = 1f; 
     data[5] = 1f; 
     data[6] = 1f; 
     data[7] = 0; 
     data[8] = 0; 
    } 

    public static Vertex createVertex(float X,float Y,float Z){ 
     return new Vertex(X,Y,Z); 
    } 

    public static FloatBuffer toBuffer(Vertex[] vertices,FloatBuffer buf){ 
     if(buf == null){ 
      buf = BufferUtils.createFloatBuffer(vertices.length * SIZE); 
     } 
     //FloatBuffer ret = BufferUtils.createFloatBuffer(vertices.length * SIZE); 

     for(Vertex v : vertices){ 
      buf.put(v.data); 
     } 

     buf.flip(); 

     return buf; 
    } 

    public static FloatBuffer toBuffer(Vertex[] vertices){ 
     return toBuffer(vertices,null); 
    } 

    public Vertex addToBuffer(FloatBuffer buf){ 
     buf.put(data); 

     return this; 
    } 

    public Vertex set(float X,float Y,float Z){ 
     data[0] = X; 
     data[1] = Y; 
     data[2] = Z; 

     return this; 
    } 

    public float getX(){ 
     return data[0]; 
    } 

    public float getY(){ 
     return data[1]; 
    } 

    public float getZ(){ 
     return data[2]; 
    } 

    public Vertex setX(float X){ 
     data[0] = X; 

     return this; 
    } 

    public Vertex setY(float Y){ 
     data[1] = Y; 

     return this; 
    } 

    public Vertex setZ(float Z){ 
     data[2] = Z; 

     return this; 
    } 

    public Vertex setColor(float R,float G,float B,float A){ 
     data[3] = R; 
     data[4] = G; 
     data[5] = B; 
     data[6] = A; 

     return this; 
    } 

    public Vertex setColor(float R,float G,float B){ 
     return setColor(R,G,B,1f); 
    } 

    public Vertex setUV(float U,float V){ 
     data[7] = U; 
     data[8] = V; 

     return this; 
    } 
} 

編集2

オブジェクトIDは、私のVBOに関連付けられたIDです。 私はいくつかのディンキーなメモリ管理をやっているので、そうするためには十分な量のメモリを移動する必要があります。私が持っている最良のアイデアは、バッファ(bufferID)に移動してから、バッファからVBOにコピーする必要があるすべてのデータをロードすることでした。ジオメトリがforループ内の "updateVBO"メソッドの内部にロードされています。

編集3、

を明確にするという考えは、地形の複数の「層」を分離するために、しかし、1つVBOのすべての内部、それを維持することです。 まず、VBOを割り当て、地形が操作されると、影響を受けた各「レイヤー」を「再計算」します。 地形の各「レイヤー」には、VBOのスペースが割り当てられます。 "レイヤー"に地形を追加または削除すると、その "レイヤー"のサイズが変更されます。つまり、VBOの他のすべてのレイヤーでオフセットを変更する必要があります。 VBOの実際のデータを "シフト"するには、自分のVBOからバッファに移動する必要があるデータを "コピー"し、バッファからVBOにデータを "コピー"するだけです正しいオフセットで私は同じVAOにRectManagersのすべてを結合していたときに、それらはすべて、彼らはどちらかの共有に思えるか、同じメモリ領域をオーバーラップする異なるバッファオブジェクトを持っているにもかかわらずことを発見しました

+0

'Vertex'はLWJGLクラスですか?そうでない場合は、ソースコードを提供できますか? – Xirema

+0

ちょうど頂点クラスを追加しましたが、実際にはデータを挿入するだけです。 – ZZT

+0

'bufferID'と' objectID'は何ですか?あなたのジオメトリはどこですか? – elect

答えて

0

...

私は」この回答をもっと早く報告してください。

0

私たちが話している幾何学的な大きさ(絶対的に低い)が与えられれば、各層に異なるvaoを使うことができます。しかし、それが価値があるかどうかを常に知る必要があります。

1つのvboの中にすべてのレイヤーをロードしたい場合、それを行うことができます。そしてそれを正しくしたい場合は、すでに行っているようにglCopyBufferSubDataを使うべきです。

とにかく、objectIDbufferIDの両方が、バッファまたは頂点バッファオブジェクトと同じ型を正確に参照することに注意してください。彼らはではなく、異なるオブジェクトです。

これは、正しいサイズの新しいvboを割り当てて、有効なレイヤーをすべて直接転送してから使用することをレイヤーが変更したときに使用することを意味します。他のコピーは必要ありません。

問題が発生する可能性があることの1つは、glCopyBufferSubDataを使用する場合、たとえば、hereのような送信元と送信先のバッファが明確であることです。

glCopyBufferSubDataに電話すると、まだGL_ARRAY_BUFFERにバインドされているものを再度確認してください。 GL_COPY_READ_BUFFERを使用して最初の作業を行い、GL_ARRAY_BUFFERに切り替えようとするとよいでしょう。

+0

ああ、応答のおかげで;私が混乱しているのは、メインバッファ(objectID)を再割り当てしないと、そのセクションだけをマップした場合、すべてのデータが保持されるということです。もう一つのバーマーは、チャンクあたり〜3000の頂点を持ち、16のチャンクをレンダリングします。私は300fpsに落とします...それをどのように増やすかわからない...配列とオブジェクトをそれぞれのチャンクにバインドしてから、 drawArray、だから私はうんざりです。 – ZZT

+0

まったく別の方法を使用し、VBO EVERY TIMEデータを再割り当てすることは変わっています。それらはすべて同じarrayIDを使用するまで素晴らしいものです。 – ZZT

関連する問題