LWJGL 2.9.3,无法为每个VAO绘制多个VBO

时间:2016-03-29 05:54:00

标签: java opengl lwjgl

我会直接进入它,下面是我的类“RectManager”的代码转储我的问题是一个奇怪的opengl问题,我正在使用lwjgl 2.9.3,并且我的显卡每个VBO的椎骨限制是33000

我的课程的作用是将一组正方形简化为一系列矩形,然后将这些数据缓冲到VBO中并根据请求绘制它。

现在我遇到的问题是我会将几个RectManager实例分组以绘制许多不同的网格,但是,如果我不为每个RectManager实例提供不同的VAO,则只会绘制第一个实例;而且我不知道为什么。 任何关于这个问题的煽动都将不胜感激。

请记住,两个示例都有多个RectManager实例(确切地说是6个)。

当我使用相同的VAO时

当我使用不同的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;
            }
        }
    }
}

修改

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

objectID是与我的VBO关联的ID。 我正在做一些极简的内存管理,我需要转移大量的内存才能这样做。我最好的想法是加载我需要移位到缓冲区(bufferID)的所有数据,然后从缓冲区复制回VBO。几何体正在for循环中的“updateVBO”方法内加载。

修改3,澄清

这个想法是将地形的多个“层”分开,但要将它们全部保存在一个VBO中。 首先,我分配VBO,然后当地形被操纵时,我“重新计算”受影响的每个“层”。 地形的每个“层”在VBO中分配一定量的空间。 当从“层”添加或移除地形时,该“层”的大小根据改变,意味着VBO中的所有其他层需要改变其偏移。 为了“移动”VBO中的实际数据,我唯一能做的就是“复制”需要从VBO转移到缓冲区的数据,然后将数据从缓冲区“复制”回到VBO中正确的偏移量。

2 个答案:

答案 0 :(得分:0)

我发现当我将所有RectManagers绑定到同一个VAO时,即使它们都有不同的缓冲区对象,它们似乎要共享或重叠相同的内存区域......

我会尽快报告并更新此答案并提供更多信息。

答案 1 :(得分:0)

你应该知道,考虑到我们所讨论的几何数量(绝对低),你可以为每一层使用不同的vao。但是,您应该始终了解它是否值得。

说,如果你想在一个vbo中加载每一层,你就可以做到。如果你想做得对,你应该像你现在一样使用glCopyBufferSubData

无论如何,您应该知道objectIDbufferID都指向相同的类型,即缓冲区或顶点缓冲区对象。它们不是不同的对象。

这意味着当一个图层改变你应该做的是分配一个具有正确大小的新vbo并直接传输其中的所有有效图层然后使用它。不需要其他副本。

可能导致问题的一个原因是,当您使用glCopyBufferSubData时,您应该明确说明源缓冲区和目标缓冲区是什么,例如here

请在致电GL_ARRAY_BUFFER时仔细检查仍然绑定到glCopyBufferSubData的内容。您可能希望使用GL_COPY_READ_BUFFER让第一件事情发挥作用,然后尝试切换到GL_ARRAY_BUFFER