diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java index cccfe7249..a509d6422 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java @@ -35,375 +35,375 @@ import java.util.stream.Stream; public class RenderableBoxGroup extends AbstractList implements IDhApiRenderableBoxGroup, Closeable +{ + private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class); + private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + public static final AtomicInteger NEXT_ID_ATOMIC_INT = new AtomicInteger(0); + + + + public final long id; + + public final String resourceLocationNamespace; + public final String resourceLocationPath; + + /** If false the boxes will be positioned relative to the level's origin */ + public final boolean positionBoxesRelativeToGroupOrigin; + + private final List boxList; + /** backup list which allows for uploading the boxes even it the main list is being modified on a different thread. */ + private final List uploadBoxList; + private final DhApiVec3d originBlockPos; + + + public boolean active = true; + public boolean ssaoEnabled = true; + private boolean vertexDataDirty = true; + + public byte skyLight = LodUtil.MAX_MC_LIGHT; + public byte blockLight = LodUtil.MIN_MC_LIGHT; + public DhApiRenderableBoxGroupShading shading = DhApiRenderableBoxGroupShading.getDefaultShaded(); + + @Nullable + public Consumer beforeRenderFunc; + public Consumer afterRenderFunc; + + // instance data + public int instanceColorVbo = 0; + public int instanceMaterialVbo = 0; + public int instanceScaleVbo = 0; + public int instanceChunkPosVbo = 0; + public int instanceSubChunkPosVbo = 0; + + public int uploadedBoxCount = -1; + + + //=================// + // getters/setters // + //=================// + //region + + @Override + public long getId() { return this.id; } + + @Override + public String getResourceLocationNamespace() { return this.resourceLocationNamespace; } + @Override + public String getResourceLocationPath() { return this.resourceLocationPath; } + + @Override + public void setOriginBlockPos(DhApiVec3d pos) { - private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class); - private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); - - public static final AtomicInteger NEXT_ID_ATOMIC_INT = new AtomicInteger(0); - - - - public final long id; - - public final String resourceLocationNamespace; - public final String resourceLocationPath; - - /** If false the boxes will be positioned relative to the level's origin */ - public final boolean positionBoxesRelativeToGroupOrigin; - - private final List boxList; - /** backup list which allows for uploading the boxes even it the main list is being modified on a different thread. */ - private final List uploadBoxList; - private final DhApiVec3d originBlockPos; - - - public boolean active = true; - public boolean ssaoEnabled = true; - private boolean vertexDataDirty = true; - - public byte skyLight = LodUtil.MAX_MC_LIGHT; - public byte blockLight = LodUtil.MIN_MC_LIGHT; - public DhApiRenderableBoxGroupShading shading = DhApiRenderableBoxGroupShading.getDefaultShaded(); - - @Nullable - public Consumer beforeRenderFunc; - public Consumer afterRenderFunc; - - // instance data - public int instanceColorVbo = 0; - public int instanceMaterialVbo = 0; - public int instanceScaleVbo = 0; - public int instanceChunkPosVbo = 0; - public int instanceSubChunkPosVbo = 0; - - public int uploadedBoxCount = -1; - - - //=================// - // getters/setters // - //=================// - //region - - @Override - public long getId() { return this.id; } - - @Override - public String getResourceLocationNamespace() { return this.resourceLocationNamespace; } - @Override - public String getResourceLocationPath() { return this.resourceLocationPath; } - - @Override - public void setOriginBlockPos(DhApiVec3d pos) - { - this.originBlockPos.x = pos.x; - this.originBlockPos.y = pos.y; - this.originBlockPos.z = pos.z; - } - - @Override - public DhApiVec3d getOriginBlockPos() { return new DhApiVec3d(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); } - - - @Override - public void setSkyLight(int skyLight) - { - if (skyLight < LodUtil.MIN_MC_LIGHT - || skyLight > LodUtil.MAX_MC_LIGHT) - { - throw new IllegalArgumentException("Sky light ["+skyLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive)."); - } - this.skyLight = (byte)skyLight; - } - @Override - public int getSkyLight() { return this.skyLight; } - - @Override - public void setBlockLight(int blockLight) - { - if (blockLight < LodUtil.MIN_MC_LIGHT - || blockLight > LodUtil.MAX_MC_LIGHT) - { - throw new IllegalArgumentException("Block light ["+blockLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive)."); - } - this.blockLight = (byte)blockLight; - } - @Override - public int getBlockLight() { return this.blockLight; } - - @Override - public void setPreRenderFunc(Consumer func) { this.beforeRenderFunc = func; } - - @Override - public void setPostRenderFunc(Consumer func) { this.afterRenderFunc = func; } - - @Override - public void setActive(boolean active) { this.active = active; } - @Override - public boolean isActive() { return this.active; } - - @Override - public void setSsaoEnabled(boolean ssaoEnabled) { this.ssaoEnabled = ssaoEnabled; } - @Override - public boolean isSsaoEnabled() { return this.ssaoEnabled; } - - @Override - public void setShading(DhApiRenderableBoxGroupShading shading) { this.shading = shading; } - @Override - public DhApiRenderableBoxGroupShading getShading() { return this.shading; } - - //endregion - - - - //=============// - // constructor // - //=============// - //region - - public RenderableBoxGroup( - String resourceLocation, - DhApiVec3d originBlockPos, List boxList, - boolean positionBoxesRelativeToGroupOrigin) throws IllegalArgumentException - { - String[] splitResourceLocation = resourceLocation.split(":"); - if (splitResourceLocation.length != 2) - { - throw new IllegalArgumentException("Resource Location must be a string that's separated by a single colon, for example: [DistantHorizons:Beacons], your namespace ["+resourceLocation+"], contains ["+(splitResourceLocation.length-1)+"] colons."); - } - - this.resourceLocationNamespace = splitResourceLocation[0]; - this.resourceLocationPath = splitResourceLocation[1]; - - this.id = NEXT_ID_ATOMIC_INT.getAndIncrement(); - this.boxList = Collections.synchronizedList(new ArrayList<>(boxList)); - this.uploadBoxList = Collections.synchronizedList(new ArrayList<>(boxList)); - - this.originBlockPos = originBlockPos; - this.positionBoxesRelativeToGroupOrigin = positionBoxesRelativeToGroupOrigin; - } - - //endregion - - - - //=================// - // render building // - //=================// - //region - - @Override - public void triggerBoxChange() { this.vertexDataDirty = true; } - - /** Does nothing if the vertex data is already up-to-date */ - public void updateVertexAttributeData() - { - if (!this.vertexDataDirty) - { - return; - } - this.vertexDataDirty = false; - - if (this.instanceChunkPosVbo == 0) - { - this.instanceChunkPosVbo = GLMC.glGenBuffers(); - this.instanceSubChunkPosVbo = GLMC.glGenBuffers(); - this.instanceScaleVbo = GLMC.glGenBuffers(); - this.instanceColorVbo = GLMC.glGenBuffers(); - this.instanceMaterialVbo = GLMC.glGenBuffers(); - } - - // copy over the box list so we can upload without concurrent modification issues - this.uploadBoxList.clear(); - synchronized (this.uploadBoxList) - { - this.uploadBoxList.addAll(this.boxList); - } - - - int boxCount = this.uploadBoxList.size(); - this.uploadedBoxCount = boxCount; - - - - // transformation / scaling // - int[] chunkPosData = RenderBoxArrayCache.getCachedIntArray(boxCount * 3, 0); - float[] subChunkPosData = RenderBoxArrayCache.getCachedFloatArray(boxCount * 3, 1); - float[] scalingData = RenderBoxArrayCache.getCachedFloatArray(boxCount * 3, 2); - for (int i = 0; i < boxCount; i++) - { - DhApiRenderableBox box = this.uploadBoxList.get(i); - - int dataIndex = i * 3; - - chunkPosData[dataIndex] = LodUtil.getChunkPosFromDouble(box.minPos.x); - chunkPosData[dataIndex + 1] = LodUtil.getChunkPosFromDouble(box.minPos.y); - chunkPosData[dataIndex + 2] = LodUtil.getChunkPosFromDouble(box.minPos.z); - - subChunkPosData[dataIndex] = LodUtil.getSubChunkPosFromDouble(box.minPos.x); - subChunkPosData[dataIndex + 1] = LodUtil.getSubChunkPosFromDouble(box.minPos.y); - subChunkPosData[dataIndex + 2] = LodUtil.getSubChunkPosFromDouble(box.minPos.z); - - scalingData[dataIndex] = (float) (box.maxPos.x - box.minPos.x); - scalingData[dataIndex + 1] = (float) (box.maxPos.y - box.minPos.y); - scalingData[dataIndex + 2] = (float) (box.maxPos.z - box.minPos.z); - - } - - - // colors/materials // - float[] colorData = RenderBoxArrayCache.getCachedFloatArray(boxCount * 4, 3); - int[] materialData = RenderBoxArrayCache.getCachedIntArray(boxCount, 4); - for (int i = 0; i < boxCount; i++) - { - DhApiRenderableBox box = this.uploadBoxList.get(i); - Color color = box.color; - int colorIndex = i * 4; - colorData[colorIndex] = color.getRed() / 255.0f; - colorData[colorIndex + 1] = color.getGreen() / 255.0f; - colorData[colorIndex + 2] = color.getBlue() / 255.0f; - colorData[colorIndex + 3] = color.getAlpha() / 255.0f; - - materialData[i] = box.material; - } - - - // Upload transformation matrices - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceChunkPosVbo); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, chunkPosData, GL32.GL_DYNAMIC_DRAW); - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceSubChunkPosVbo); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, subChunkPosData, GL32.GL_DYNAMIC_DRAW); - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVbo); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, scalingData, GL32.GL_DYNAMIC_DRAW); - - // Upload colors - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVbo); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colorData, GL32.GL_DYNAMIC_DRAW); - - // Upload materials - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceMaterialVbo); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, materialData, GL32.GL_DYNAMIC_DRAW); - } - - //endregion - - - - //===============// - // render events // - //===============// - //region - - /** - * This is called before every frame, even if {@link this#isActive()} returns false.
- * {@link this#isActive()} can be changed at this point before the object is rendered to the frame. - */ - public void preRender(DhApiRenderParam renderEventParam) - { - if (this.beforeRenderFunc != null) - { - this.beforeRenderFunc.accept(renderEventParam); - } - } - /** - * Called after rendering is completed.
- * Can be used to handle any necessary cleanup. - */ - public void postRender(DhApiRenderParam renderEventParam) - { - if (this.afterRenderFunc != null) - { - this.afterRenderFunc.accept(renderEventParam); - } - } - - //endregion - - - - //================// - // List Overrides // - //================// - //region - - @Override - public boolean add(DhApiRenderableBox box) { return this.boxList.add(box); } - @Override - public DhApiRenderableBox get(int index) { return this.boxList.get(index); } - @Override - public int size() { return this.boxList.size(); } - @Override - public boolean removeIf(Predicate filter) { return this.boxList.removeIf(filter); } - @Override - public boolean remove(Object obj) { return this.boxList.remove(obj); } - @Override - public DhApiRenderableBox remove(int index) { return this.boxList.remove(index); } - @Override - public void replaceAll(UnaryOperator operator) { this.boxList.replaceAll(operator); } - @Override - public void sort(Comparator comparator) { this.boxList.sort(comparator); } - @Override - public void forEach(Consumer action) { this.boxList.forEach(action); } - @Override - public Spliterator spliterator() { return this.boxList.spliterator(); } - @Override - public Stream stream() { return this.boxList.stream(); } - @Override - public Stream parallelStream() { return this.boxList.parallelStream(); } - @Override - public void clear() { this.boxList.clear(); } - - //endregion - - - - //================// - // base overrides // - //================// - //region - - @Override - public String toString() { return "ID:["+this.id+"], pos:["+this.originBlockPos.x+","+this.originBlockPos.y+","+this.originBlockPos.z+"], size:["+this.size()+"], active:["+this.active+"]"; } - - @Override - public void close() - { - GLProxy.queueRunningOnRenderThread(() -> - { - if (this.instanceChunkPosVbo != 0) - { - GLMC.glDeleteBuffers(this.instanceChunkPosVbo); - this.instanceChunkPosVbo = 0; - } - - if (this.instanceSubChunkPosVbo != 0) - { - GLMC.glDeleteBuffers(this.instanceSubChunkPosVbo); - this.instanceSubChunkPosVbo = 0; - } - - if (this.instanceScaleVbo != 0) - { - GLMC.glDeleteBuffers(this.instanceScaleVbo); - this.instanceScaleVbo = 0; - } - - if (this.instanceColorVbo != 0) - { - GLMC.glDeleteBuffers(this.instanceColorVbo); - this.instanceColorVbo = 0; - } - - if (this.instanceMaterialVbo != 0) - { - GLMC.glDeleteBuffers(this.instanceMaterialVbo); - this.instanceMaterialVbo = 0; - } - }); - } - - //endregion - - - + this.originBlockPos.x = pos.x; + this.originBlockPos.y = pos.y; + this.originBlockPos.z = pos.z; } + + @Override + public DhApiVec3d getOriginBlockPos() { return new DhApiVec3d(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); } + + + @Override + public void setSkyLight(int skyLight) + { + if (skyLight < LodUtil.MIN_MC_LIGHT + || skyLight > LodUtil.MAX_MC_LIGHT) + { + throw new IllegalArgumentException("Sky light ["+skyLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive)."); + } + this.skyLight = (byte)skyLight; + } + @Override + public int getSkyLight() { return this.skyLight; } + + @Override + public void setBlockLight(int blockLight) + { + if (blockLight < LodUtil.MIN_MC_LIGHT + || blockLight > LodUtil.MAX_MC_LIGHT) + { + throw new IllegalArgumentException("Block light ["+blockLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive)."); + } + this.blockLight = (byte)blockLight; + } + @Override + public int getBlockLight() { return this.blockLight; } + + @Override + public void setPreRenderFunc(Consumer func) { this.beforeRenderFunc = func; } + + @Override + public void setPostRenderFunc(Consumer func) { this.afterRenderFunc = func; } + + @Override + public void setActive(boolean active) { this.active = active; } + @Override + public boolean isActive() { return this.active; } + + @Override + public void setSsaoEnabled(boolean ssaoEnabled) { this.ssaoEnabled = ssaoEnabled; } + @Override + public boolean isSsaoEnabled() { return this.ssaoEnabled; } + + @Override + public void setShading(DhApiRenderableBoxGroupShading shading) { this.shading = shading; } + @Override + public DhApiRenderableBoxGroupShading getShading() { return this.shading; } + + //endregion + + + + //=============// + // constructor // + //=============// + //region + + public RenderableBoxGroup( + String resourceLocation, + DhApiVec3d originBlockPos, List boxList, + boolean positionBoxesRelativeToGroupOrigin) throws IllegalArgumentException + { + String[] splitResourceLocation = resourceLocation.split(":"); + if (splitResourceLocation.length != 2) + { + throw new IllegalArgumentException("Resource Location must be a string that's separated by a single colon, for example: [DistantHorizons:Beacons], your namespace ["+resourceLocation+"], contains ["+(splitResourceLocation.length-1)+"] colons."); + } + + this.resourceLocationNamespace = splitResourceLocation[0]; + this.resourceLocationPath = splitResourceLocation[1]; + + this.id = NEXT_ID_ATOMIC_INT.getAndIncrement(); + this.boxList = Collections.synchronizedList(new ArrayList<>(boxList)); + this.uploadBoxList = Collections.synchronizedList(new ArrayList<>(boxList)); + + this.originBlockPos = originBlockPos; + this.positionBoxesRelativeToGroupOrigin = positionBoxesRelativeToGroupOrigin; + } + + //endregion + + + + //=================// + // render building // + //=================// + //region + + @Override + public void triggerBoxChange() { this.vertexDataDirty = true; } + + /** Does nothing if the vertex data is already up-to-date */ + public void updateVertexAttributeData() + { + if (!this.vertexDataDirty) + { + return; + } + this.vertexDataDirty = false; + + if (this.instanceChunkPosVbo == 0) + { + this.instanceChunkPosVbo = GLMC.glGenBuffers(); + this.instanceSubChunkPosVbo = GLMC.glGenBuffers(); + this.instanceScaleVbo = GLMC.glGenBuffers(); + this.instanceColorVbo = GLMC.glGenBuffers(); + this.instanceMaterialVbo = GLMC.glGenBuffers(); + } + + // copy over the box list so we can upload without concurrent modification issues + this.uploadBoxList.clear(); + synchronized (this.uploadBoxList) + { + this.uploadBoxList.addAll(this.boxList); + } + + + int boxCount = this.uploadBoxList.size(); + this.uploadedBoxCount = boxCount; + + + + // transformation / scaling // + int[] chunkPosData = RenderBoxArrayCache.getCachedIntArray(boxCount * 3, 0); + float[] subChunkPosData = RenderBoxArrayCache.getCachedFloatArray(boxCount * 3, 1); + float[] scalingData = RenderBoxArrayCache.getCachedFloatArray(boxCount * 3, 2); + for (int i = 0; i < boxCount; i++) + { + DhApiRenderableBox box = this.uploadBoxList.get(i); + + int dataIndex = i * 3; + + chunkPosData[dataIndex] = LodUtil.getChunkPosFromDouble(box.minPos.x); + chunkPosData[dataIndex + 1] = LodUtil.getChunkPosFromDouble(box.minPos.y); + chunkPosData[dataIndex + 2] = LodUtil.getChunkPosFromDouble(box.minPos.z); + + subChunkPosData[dataIndex] = LodUtil.getSubChunkPosFromDouble(box.minPos.x); + subChunkPosData[dataIndex + 1] = LodUtil.getSubChunkPosFromDouble(box.minPos.y); + subChunkPosData[dataIndex + 2] = LodUtil.getSubChunkPosFromDouble(box.minPos.z); + + scalingData[dataIndex] = (float) (box.maxPos.x - box.minPos.x); + scalingData[dataIndex + 1] = (float) (box.maxPos.y - box.minPos.y); + scalingData[dataIndex + 2] = (float) (box.maxPos.z - box.minPos.z); + + } + + + // colors/materials // + float[] colorData = RenderBoxArrayCache.getCachedFloatArray(boxCount * 4, 3); + int[] materialData = RenderBoxArrayCache.getCachedIntArray(boxCount, 4); + for (int i = 0; i < boxCount; i++) + { + DhApiRenderableBox box = this.uploadBoxList.get(i); + Color color = box.color; + int colorIndex = i * 4; + colorData[colorIndex] = color.getRed() / 255.0f; + colorData[colorIndex + 1] = color.getGreen() / 255.0f; + colorData[colorIndex + 2] = color.getBlue() / 255.0f; + colorData[colorIndex + 3] = color.getAlpha() / 255.0f; + + materialData[i] = box.material; + } + + + // Upload transformation matrices + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceChunkPosVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, chunkPosData, GL32.GL_DYNAMIC_DRAW); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceSubChunkPosVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, subChunkPosData, GL32.GL_DYNAMIC_DRAW); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, scalingData, GL32.GL_DYNAMIC_DRAW); + + // Upload colors + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colorData, GL32.GL_DYNAMIC_DRAW); + + // Upload materials + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceMaterialVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, materialData, GL32.GL_DYNAMIC_DRAW); + } + + //endregion + + + + //===============// + // render events // + //===============// + //region + + /** + * This is called before every frame, even if {@link this#isActive()} returns false.
+ * {@link this#isActive()} can be changed at this point before the object is rendered to the frame. + */ + public void preRender(DhApiRenderParam renderEventParam) + { + if (this.beforeRenderFunc != null) + { + this.beforeRenderFunc.accept(renderEventParam); + } + } + /** + * Called after rendering is completed.
+ * Can be used to handle any necessary cleanup. + */ + public void postRender(DhApiRenderParam renderEventParam) + { + if (this.afterRenderFunc != null) + { + this.afterRenderFunc.accept(renderEventParam); + } + } + + //endregion + + + + //================// + // List Overrides // + //================// + //region + + @Override + public boolean add(DhApiRenderableBox box) { return this.boxList.add(box); } + @Override + public DhApiRenderableBox get(int index) { return this.boxList.get(index); } + @Override + public int size() { return this.boxList.size(); } + @Override + public boolean removeIf(Predicate filter) { return this.boxList.removeIf(filter); } + @Override + public boolean remove(Object obj) { return this.boxList.remove(obj); } + @Override + public DhApiRenderableBox remove(int index) { return this.boxList.remove(index); } + @Override + public void replaceAll(UnaryOperator operator) { this.boxList.replaceAll(operator); } + @Override + public void sort(Comparator comparator) { this.boxList.sort(comparator); } + @Override + public void forEach(Consumer action) { this.boxList.forEach(action); } + @Override + public Spliterator spliterator() { return this.boxList.spliterator(); } + @Override + public Stream stream() { return this.boxList.stream(); } + @Override + public Stream parallelStream() { return this.boxList.parallelStream(); } + @Override + public void clear() { this.boxList.clear(); } + + //endregion + + + + //================// + // base overrides // + //================// + //region + + @Override + public String toString() { return "ID:["+this.id+"], pos:["+this.originBlockPos.x+","+this.originBlockPos.y+","+this.originBlockPos.z+"], size:["+this.size()+"], active:["+this.active+"]"; } + + @Override + public void close() + { + GLProxy.queueRunningOnRenderThread(() -> + { + if (this.instanceChunkPosVbo != 0) + { + GLMC.glDeleteBuffers(this.instanceChunkPosVbo); + this.instanceChunkPosVbo = 0; + } + + if (this.instanceSubChunkPosVbo != 0) + { + GLMC.glDeleteBuffers(this.instanceSubChunkPosVbo); + this.instanceSubChunkPosVbo = 0; + } + + if (this.instanceScaleVbo != 0) + { + GLMC.glDeleteBuffers(this.instanceScaleVbo); + this.instanceScaleVbo = 0; + } + + if (this.instanceColorVbo != 0) + { + GLMC.glDeleteBuffers(this.instanceColorVbo); + this.instanceColorVbo = 0; + } + + if (this.instanceMaterialVbo != 0) + { + GLMC.glDeleteBuffers(this.instanceMaterialVbo); + this.instanceMaterialVbo = 0; + } + }); + } + + //endregion + + + +} \ No newline at end of file