我会直接进入它,下面是我的类“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中正确的偏移量。
答案 0 :(得分:0)
我发现当我将所有RectManagers绑定到同一个VAO时,即使它们都有不同的缓冲区对象,它们似乎要共享或重叠相同的内存区域......
我会尽快报告并更新此答案并提供更多信息。
答案 1 :(得分:0)
你应该知道,考虑到我们所讨论的几何数量(绝对低),你可以为每一层使用不同的vao。但是,您应该始终了解它是否值得。
说,如果你想在一个vbo中加载每一层,你就可以做到。如果你想做得对,你应该像你现在一样使用glCopyBufferSubData
。
无论如何,您应该知道objectID
和bufferID
都指向相同的类型,即缓冲区或顶点缓冲区对象。它们不是不同的对象。
这意味着当一个图层改变你应该做的是分配一个具有正确大小的新vbo并直接传输其中的所有有效图层然后使用它。不需要其他副本。
可能导致问题的一个原因是,当您使用glCopyBufferSubData
时,您应该明确说明源缓冲区和目标缓冲区是什么,例如here。
请在致电GL_ARRAY_BUFFER
时仔细检查仍然绑定到glCopyBufferSubData
的内容。您可能希望使用GL_COPY_READ_BUFFER
让第一件事情发挥作用,然后尝试切换到GL_ARRAY_BUFFER
。