私はそのクラスに「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のすべてを結合していたときに、それらはすべて、彼らはどちらかの共有に思えるか、同じメモリ領域をオーバーラップする異なるバッファオブジェクトを持っているにもかかわらずことを発見しました
'Vertex'はLWJGLクラスですか?そうでない場合は、ソースコードを提供できますか? – Xirema
ちょうど頂点クラスを追加しましたが、実際にはデータを挿入するだけです。 – ZZT
'bufferID'と' objectID'は何ですか?あなたのジオメトリはどこですか? – elect