mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-27 23:47:09 +01:00
State your state
- Address a few bugs with rubidium - Ignore EBOs when restoring state - ElementBuffer deals in raw gl handles - Document all state changes/restores/resets Co-authored-by: PepperCode1 <44146161+peppercode1@users.noreply.github.com>
This commit is contained in:
parent
6c11958b9e
commit
9280ae50dd
13 changed files with 114 additions and 84 deletions
|
@ -39,7 +39,7 @@ public class GlStateTracker {
|
||||||
return new State(BUFFERS.clone(), vao, program);
|
return new State(BUFFERS.clone(), vao, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static record State(int[] buffers, int vao, int program) {
|
public record State(int[] buffers, int vao, int program) {
|
||||||
public void restore() {
|
public void restore() {
|
||||||
if (vao != GlStateTracker.vao) {
|
if (vao != GlStateTracker.vao) {
|
||||||
GlStateManager._glBindVertexArray(vao);
|
GlStateManager._glBindVertexArray(vao);
|
||||||
|
@ -48,7 +48,7 @@ public class GlStateTracker {
|
||||||
GlBufferType[] values = GlBufferType.values();
|
GlBufferType[] values = GlBufferType.values();
|
||||||
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (int i = 0; i < values.length; i++) {
|
||||||
if (buffers[i] != GlStateTracker.BUFFERS[i]) {
|
if (buffers[i] != GlStateTracker.BUFFERS[i] && values[i] != GlBufferType.ELEMENT_ARRAY_BUFFER) {
|
||||||
GlStateManager._glBindBuffer(values[i].glEnum, buffers[i]);
|
GlStateManager._glBindBuffer(values[i].glEnum, buffers[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
public void render() {
|
public void render() {
|
||||||
if (invalid()) return;
|
if (invalid()) return;
|
||||||
|
|
||||||
|
// XXX VAO is bound and not reset or restored
|
||||||
vao.bind();
|
vao.bind();
|
||||||
|
|
||||||
renderSetup();
|
renderSetup();
|
||||||
|
@ -68,12 +69,15 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
|
|
||||||
vao = new GlVertexArray();
|
vao = new GlVertexArray();
|
||||||
|
|
||||||
|
// XXX Callback seems unnecessary. Remove and extract code to run after alloc call?
|
||||||
model = modelAllocator.alloc(modelData, arenaModel -> {
|
model = modelAllocator.alloc(modelData, arenaModel -> {
|
||||||
|
// XXX VAO is bound and not reset or restored
|
||||||
vao.bind();
|
vao.bind();
|
||||||
|
|
||||||
arenaModel.setupState(vao);
|
arenaModel.setupState(vao);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// XXX VAO is already guaranteed to be bound in model callback
|
||||||
vao.bind();
|
vao.bind();
|
||||||
vao.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount());
|
vao.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount());
|
||||||
|
|
||||||
|
@ -108,6 +112,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
removeDeletedInstances();
|
removeDeletedInstances();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX ARRAY_BUFFER is bound and reset
|
||||||
instanceVBO.bind();
|
instanceVBO.bind();
|
||||||
if (!realloc()) {
|
if (!realloc()) {
|
||||||
|
|
||||||
|
|
|
@ -68,15 +68,23 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
|
||||||
return vertexCount;
|
return vertexCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX Overriden in CrumblingGroup
|
||||||
|
// XXX Runs inside of restore state
|
||||||
public void render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
|
public void render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
|
||||||
type.setupRenderState();
|
type.setupRenderState();
|
||||||
Textures.bindActiveTextures();
|
Textures.bindActiveTextures(); // XXX Changes active unit and bound textures
|
||||||
renderAll(viewProjection, camX, camY, camZ, layer);
|
renderAll(viewProjection, camX, camY, camZ, layer); // XXX May change ARRAY_BUFFER binding (reset or not reset), VAO binding (not reset), shader binding (not reset), call Model.createEBO
|
||||||
type.clearRenderState();
|
type.clearRenderState();
|
||||||
|
// XXX Should texture bindings be reset or restored?
|
||||||
|
// XXX Should the active unit be reset or restored?
|
||||||
|
// XXX Should the VAO binding be reset or restored?
|
||||||
|
// XXX Should the ARRAY_BUFFER binding be reset or restored?
|
||||||
|
// XXX Should the shader binding be reset or restored?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX Internal GL state changes are inconsistent; sometimes bindings are reset to 0, sometimes not
|
||||||
protected void renderAll(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
|
protected void renderAll(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
|
||||||
initializeInstancers();
|
initializeInstancers(); // XXX May change ARRAY_BUFFER binding (reset or not reset), VAO binding (not reset), call Model.createEBO
|
||||||
|
|
||||||
vertexCount = 0;
|
vertexCount = 0;
|
||||||
instanceCount = 0;
|
instanceCount = 0;
|
||||||
|
@ -88,6 +96,7 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
|
||||||
P program = owner.context.getProgram(ProgramContext.create(entry.getKey()
|
P program = owner.context.getProgram(ProgramContext.create(entry.getKey()
|
||||||
.getProgramSpec(), Formats.POS_TEX_NORMAL, layer));
|
.getProgramSpec(), Formats.POS_TEX_NORMAL, layer));
|
||||||
|
|
||||||
|
// XXX Shader is bound and not reset or restored
|
||||||
program.bind();
|
program.bind();
|
||||||
program.uploadViewProjection(viewProjection);
|
program.uploadViewProjection(viewProjection);
|
||||||
program.uploadCameraPos(camX, camY, camZ);
|
program.uploadCameraPos(camX, camY, camZ);
|
||||||
|
@ -95,7 +104,7 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
|
||||||
setup(program);
|
setup(program);
|
||||||
|
|
||||||
for (GPUInstancer<?> instancer : material.getAllInstancers()) {
|
for (GPUInstancer<?> instancer : material.getAllInstancers()) {
|
||||||
instancer.render();
|
instancer.render(); // XXX May change VAO binding (not reset), ARRAY_BUFFER binding (reset)
|
||||||
vertexCount += instancer.getVertexCount();
|
vertexCount += instancer.getVertexCount();
|
||||||
instanceCount += instancer.getInstanceCount();
|
instanceCount += instancer.getInstanceCount();
|
||||||
}
|
}
|
||||||
|
@ -103,19 +112,19 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeInstancers() {
|
private void initializeInstancers() {
|
||||||
ModelAllocator allocator = getModelAllocator();
|
ModelAllocator allocator = getModelAllocator(); // XXX May change ARRAY_BUFFER binding (not reset)
|
||||||
|
|
||||||
// initialize all uninitialized instancers...
|
// initialize all uninitialized instancers...
|
||||||
for (InstancedMaterial<?> material : materials.values()) {
|
for (InstancedMaterial<?> material : materials.values()) {
|
||||||
for (GPUInstancer<?> instancer : material.uninitialized) {
|
for (GPUInstancer<?> instancer : material.uninitialized) {
|
||||||
instancer.init(allocator);
|
instancer.init(allocator); // XXX May change VAO binding (not reset), ARRAY_BUFFER binding (not reset), call Model.createEBO
|
||||||
}
|
}
|
||||||
material.uninitialized.clear();
|
material.uninitialized.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allocator instanceof ModelPool pool) {
|
if (allocator instanceof ModelPool pool) {
|
||||||
// ...and then flush the model arena in case anything was marked for upload
|
// ...and then flush the model arena in case anything was marked for upload
|
||||||
pool.flush();
|
pool.flush(); // XXX May change ARRAY_BUFFER binding (reset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void render(TaskEngine taskEngine, RenderLayerEvent event) {
|
public void render(TaskEngine taskEngine, RenderLayerEvent event) {
|
||||||
|
// XXX Restore state
|
||||||
GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
|
GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
|
||||||
|
|
||||||
double camX;
|
double camX;
|
||||||
|
|
|
@ -1,27 +1,29 @@
|
||||||
package com.jozufozu.flywheel.backend.model;
|
package com.jozufozu.flywheel.backend.model;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
|
||||||
import com.mojang.blaze3d.vertex.VertexBuffer;
|
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
|
||||||
public class ElementBuffer {
|
public class ElementBuffer {
|
||||||
|
|
||||||
private final GlBuffer buffer;
|
protected final int elementCount;
|
||||||
public final int elementCount;
|
protected final VertexFormat.IndexType eboIndexType;
|
||||||
public final VertexFormat.IndexType eboIndexType;
|
private final int glBuffer;
|
||||||
|
|
||||||
public ElementBuffer(GlBuffer backing, int elementCount, VertexFormat.IndexType indexType) {
|
public ElementBuffer(int backing, int elementCount, VertexFormat.IndexType indexType) {
|
||||||
this.buffer = backing;
|
|
||||||
this.eboIndexType = indexType;
|
|
||||||
this.elementCount = elementCount;
|
this.elementCount = elementCount;
|
||||||
|
this.eboIndexType = indexType;
|
||||||
|
this.glBuffer = backing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind() {
|
public void bind() {
|
||||||
buffer.bind();
|
GlBufferType.ELEMENT_ARRAY_BUFFER.bind(glBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unbind() {
|
public int getElementCount() {
|
||||||
buffer.unbind();
|
return elementCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VertexFormat.IndexType getEboIndexType() {
|
||||||
|
return eboIndexType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,27 +59,26 @@ public class IndexedModel implements BufferedModel {
|
||||||
* The VBO/VAO should be bound externally.
|
* The VBO/VAO should be bound externally.
|
||||||
*/
|
*/
|
||||||
public void setupState(GlVertexArray vao) {
|
public void setupState(GlVertexArray vao) {
|
||||||
|
// XXX ARRAY_BUFFER is bound and not reset or restored
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
vao.enableArrays(getAttributeCount());
|
vao.enableArrays(getAttributeCount());
|
||||||
vao.bindAttributes(0, getType().getLayout());
|
vao.bindAttributes(0, getType().getLayout());
|
||||||
|
ebo.bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawCall() {
|
public void drawCall() {
|
||||||
ebo.bind();
|
GL20.glDrawElements(primitiveMode.glEnum, ebo.getElementCount(), ebo.getEboIndexType().asGLType, 0);
|
||||||
GL20.glDrawElements(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.asGLType, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws many instances of this model, assuming the appropriate state is already bound.
|
* Draws many instances of this model, assuming the appropriate state is already bound.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void drawInstances(int instanceCount) {
|
public void drawInstances(int instanceCount) {
|
||||||
if (!valid()) return;
|
if (!valid()) return;
|
||||||
|
|
||||||
ebo.bind();
|
GL31.glDrawElementsInstanced(primitiveMode.glEnum, ebo.getElementCount(), ebo.getEboIndexType().asGLType, 0, instanceCount);
|
||||||
|
|
||||||
GL31.glDrawElementsInstanced(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.asGLType, 0, instanceCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDeleted() {
|
public boolean isDeleted() {
|
||||||
|
|
|
@ -42,6 +42,7 @@ public class ModelPool implements ModelAllocator {
|
||||||
|
|
||||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||||
|
|
||||||
|
// XXX ARRAY_BUFFER is bound and not reset or restored
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
vbo.setGrowthMargin(stride * 64);
|
vbo.setGrowthMargin(stride * 64);
|
||||||
}
|
}
|
||||||
|
@ -68,6 +69,7 @@ public class ModelPool implements ModelAllocator {
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
if (anyToRemove) processDeletions();
|
if (anyToRemove) processDeletions();
|
||||||
|
|
||||||
|
// XXX ARRAY_BUFFER is bound and reset
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
if (realloc()) {
|
if (realloc()) {
|
||||||
uploadAll();
|
uploadAll();
|
||||||
|
@ -182,25 +184,25 @@ public class ModelPool implements ModelAllocator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setupState(GlVertexArray vao) {
|
public void setupState(GlVertexArray vao) {
|
||||||
|
// XXX ARRAY_BUFFER is bound and not reset or restored
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
vao.enableArrays(getAttributeCount());
|
vao.enableArrays(getAttributeCount());
|
||||||
vao.bindAttributes(0, vertexType.getLayout());
|
vao.bindAttributes(0, vertexType.getLayout());
|
||||||
|
ebo.bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawCall() {
|
public void drawCall() {
|
||||||
GL32.glDrawElementsBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.asGLType, 0, first);
|
GL32.glDrawElementsBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.getElementCount(), ebo.getEboIndexType().asGLType, 0, first);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawInstances(int instanceCount) {
|
public void drawInstances(int instanceCount) {
|
||||||
if (!valid()) return;
|
if (!valid()) return;
|
||||||
|
|
||||||
ebo.bind();
|
|
||||||
|
|
||||||
//Backend.log.info(StringUtil.args("drawElementsInstancedBaseVertex", GlPrimitive.TRIANGLES, ebo.elementCount, ebo.eboIndexType, 0, instanceCount, first));
|
//Backend.log.info(StringUtil.args("drawElementsInstancedBaseVertex", GlPrimitive.TRIANGLES, ebo.elementCount, ebo.eboIndexType, 0, instanceCount, first));
|
||||||
|
|
||||||
GL32.glDrawElementsInstancedBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.asGLType, 0, instanceCount, first);
|
GL32.glDrawElementsInstancedBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.getElementCount(), ebo.getEboIndexType().asGLType, 0, instanceCount, first);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -58,6 +58,7 @@ public class VBOModel implements BufferedModel {
|
||||||
* The VBO/VAO should be bound externally.
|
* The VBO/VAO should be bound externally.
|
||||||
*/
|
*/
|
||||||
public void setupState(GlVertexArray vao) {
|
public void setupState(GlVertexArray vao) {
|
||||||
|
// XXX ARRAY_BUFFER is bound and not reset or restored
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
vao.enableArrays(getAttributeCount());
|
vao.enableArrays(getAttributeCount());
|
||||||
vao.bindAttributes(0, getLayout());
|
vao.bindAttributes(0, getLayout());
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
package com.jozufozu.flywheel.core;
|
package com.jozufozu.flywheel.core;
|
||||||
|
|
||||||
import java.nio.Buffer;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
import org.lwjgl.opengl.GL32C;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
||||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to manage EBOs that index quads as triangles.
|
* A class to manage EBOs that index quads as triangles.
|
||||||
*/
|
*/
|
||||||
|
@ -37,76 +37,74 @@ public class QuadConverter {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final MappedGlBuffer ebo;
|
private final Int2ReferenceMap<ElementBuffer> cache = new Int2ReferenceArrayMap<>();
|
||||||
|
private final int ebo;
|
||||||
private int quadCapacity;
|
private int quadCapacity;
|
||||||
|
|
||||||
public QuadConverter() {
|
public QuadConverter() {
|
||||||
this.ebo = new MappedGlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER);
|
this.ebo = GL32.glGenBuffers();
|
||||||
this.quadCapacity = 0;
|
this.quadCapacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ElementBuffer quads2Tris(int quads) {
|
public ElementBuffer quads2Tris(int quads) {
|
||||||
int indexCount = quads * 6;
|
|
||||||
|
|
||||||
if (quads > quadCapacity) {
|
if (quads > quadCapacity) {
|
||||||
ebo.bind();
|
grow(quads * 2);
|
||||||
ebo.ensureCapacity((long) indexCount * GlNumericType.UINT.getByteWidth());
|
|
||||||
|
|
||||||
try (MappedBuffer map = ebo.getBuffer()) {
|
|
||||||
ByteBuffer indices = map.unwrap();
|
|
||||||
|
|
||||||
fillBuffer(indices, quads);
|
|
||||||
}
|
|
||||||
ebo.unbind();
|
|
||||||
|
|
||||||
this.quadCapacity = quads;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ElementBuffer(ebo, indexCount, VertexFormat.IndexType.INT);
|
return cache.computeIfAbsent(quads, this::createElementBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private ElementBuffer createElementBuffer(int quads) {
|
||||||
|
return new ElementBuffer(ebo, quads * 6, VertexFormat.IndexType.INT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void grow(int quads) {
|
||||||
|
int byteSize = quads * 6 * GlNumericType.UINT.getByteWidth();
|
||||||
|
final long ptr = MemoryUtil.nmemAlloc(byteSize);
|
||||||
|
|
||||||
|
fillBuffer(ptr, quads);
|
||||||
|
|
||||||
|
// XXX ARRAY_BUFFER is bound and reset
|
||||||
|
final var bufferType = GlBufferType.ARRAY_BUFFER;
|
||||||
|
final int oldBuffer = bufferType.getBoundBuffer();
|
||||||
|
bufferType.bind(ebo);
|
||||||
|
GL32C.nglBufferData(bufferType.glEnum, byteSize, ptr, GlBufferUsage.STATIC_DRAW.glEnum);
|
||||||
|
bufferType.bind(oldBuffer);
|
||||||
|
|
||||||
|
MemoryUtil.nmemFree(ptr);
|
||||||
|
|
||||||
|
this.quadCapacity = quads;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
ebo.delete();
|
GL32.glDeleteBuffers(ebo);
|
||||||
this.quadCapacity = 0;
|
this.quadCapacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillBuffer(ByteBuffer indices, int quads) {
|
private void fillBuffer(long ptr, int quads) {
|
||||||
long addr = MemoryUtil.memAddress(indices);
|
|
||||||
int numVertices = 4 * quads;
|
int numVertices = 4 * quads;
|
||||||
int baseVertex = 0;
|
int baseVertex = 0;
|
||||||
while (baseVertex < numVertices) {
|
while (baseVertex < numVertices) {
|
||||||
// writeQuadIndices(indices, baseVertex);
|
writeQuadIndicesUnsafe(ptr, baseVertex);
|
||||||
writeQuadIndicesUnsafe(addr, baseVertex);
|
|
||||||
|
|
||||||
baseVertex += 4;
|
baseVertex += 4;
|
||||||
addr += 6 * 4;
|
ptr += 6 * 4;
|
||||||
}
|
}
|
||||||
// ((Buffer) indices).flip();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeQuadIndices(ByteBuffer indices, int baseVertex) {
|
private void writeQuadIndicesUnsafe(long ptr, int baseVertex) {
|
||||||
// triangle a
|
// triangle a
|
||||||
indices.putInt(baseVertex);
|
MemoryUtil.memPutInt(ptr, baseVertex);
|
||||||
indices.putInt(baseVertex + 1);
|
MemoryUtil.memPutInt(ptr + 4, baseVertex + 1);
|
||||||
indices.putInt(baseVertex + 2);
|
MemoryUtil.memPutInt(ptr + 8, baseVertex + 2);
|
||||||
// triangle b
|
// triangle b
|
||||||
indices.putInt(baseVertex);
|
MemoryUtil.memPutInt(ptr + 12, baseVertex);
|
||||||
indices.putInt(baseVertex + 2);
|
MemoryUtil.memPutInt(ptr + 16, baseVertex + 2);
|
||||||
indices.putInt(baseVertex + 3);
|
MemoryUtil.memPutInt(ptr + 20, baseVertex + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeQuadIndicesUnsafe(long addr, int baseVertex) {
|
// make sure this gets reset first, so it has a chance to repopulate
|
||||||
// triangle a
|
|
||||||
MemoryUtil.memPutInt(addr, baseVertex);
|
|
||||||
MemoryUtil.memPutInt(addr + 4, baseVertex + 1);
|
|
||||||
MemoryUtil.memPutInt(addr + 8, baseVertex + 2);
|
|
||||||
// triangle b
|
|
||||||
MemoryUtil.memPutInt(addr + 12, baseVertex);
|
|
||||||
MemoryUtil.memPutInt(addr + 16, baseVertex + 2);
|
|
||||||
MemoryUtil.memPutInt(addr + 20, baseVertex + 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure this gets reset first so it has a chance to repopulate
|
|
||||||
public static void onRendererReload(ReloadRenderersEvent event) {
|
public static void onRendererReload(ReloadRenderersEvent event) {
|
||||||
if (INSTANCE != null) {
|
if (INSTANCE != null) {
|
||||||
INSTANCE.delete();
|
INSTANCE.delete();
|
||||||
|
|
|
@ -18,6 +18,7 @@ public class CrumblingGroup<P extends CrumblingProgram> extends InstancedMateria
|
||||||
super(owner, type);
|
super(owner, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX See notes of overriden method
|
||||||
@Override
|
@Override
|
||||||
public void render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
|
public void render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
|
||||||
type.setupRenderState();
|
type.setupRenderState();
|
||||||
|
|
|
@ -65,6 +65,7 @@ public class CrumblingRenderer {
|
||||||
|
|
||||||
Vec3 cameraPos = camera.getPosition();
|
Vec3 cameraPos = camera.getPosition();
|
||||||
|
|
||||||
|
// XXX Restore state
|
||||||
GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
|
GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
|
||||||
CrumblingRenderer.renderBreaking(activeStages, new RenderLayerEvent(level, null, stack, null, cameraPos.x, cameraPos.y, cameraPos.z));
|
CrumblingRenderer.renderBreaking(activeStages, new RenderLayerEvent(level, null, stack, null, cameraPos.x, cameraPos.y, cameraPos.z));
|
||||||
restoreState.restore();
|
restoreState.restore();
|
||||||
|
@ -87,6 +88,7 @@ public class CrumblingRenderer {
|
||||||
|
|
||||||
instanceManager.beginFrame(SerialTaskEngine.INSTANCE, info);
|
instanceManager.beginFrame(SerialTaskEngine.INSTANCE, info);
|
||||||
|
|
||||||
|
// XXX Each call applies another restore state even though we are already inside of a restore state
|
||||||
materials.render(SerialTaskEngine.INSTANCE, event);
|
materials.render(SerialTaskEngine.INSTANCE, event);
|
||||||
|
|
||||||
instanceManager.invalidate();
|
instanceManager.invalidate();
|
||||||
|
@ -94,6 +96,9 @@ public class CrumblingRenderer {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX Inconsistent GL state cleanup
|
||||||
|
// If texture binding and active unit need to be restored, store them in variables before GL state is changed
|
||||||
|
// instead of guessing that unit 0 and crumbling tex 0 are correct
|
||||||
GlTextureUnit.T0.makeActive();
|
GlTextureUnit.T0.makeActive();
|
||||||
AbstractTexture breaking = textureManager.getTexture(ModelBakery.BREAKING_LOCATIONS.get(0));
|
AbstractTexture breaking = textureManager.getTexture(ModelBakery.BREAKING_LOCATIONS.get(0));
|
||||||
if (breaking != null) RenderSystem.bindTexture(breaking.getId());
|
if (breaking != null) RenderSystem.bindTexture(breaking.getId());
|
||||||
|
|
|
@ -3,13 +3,14 @@ package com.jozufozu.flywheel.core.model;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL15;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
||||||
import com.jozufozu.flywheel.core.Formats;
|
import com.jozufozu.flywheel.core.Formats;
|
||||||
import com.jozufozu.flywheel.core.QuadConverter;
|
import com.jozufozu.flywheel.core.QuadConverter;
|
||||||
|
@ -64,10 +65,15 @@ public class BlockModel implements Model {
|
||||||
ByteBuffer indexBuffer = MemoryTracker.create(src.capacity());
|
ByteBuffer indexBuffer = MemoryTracker.create(src.capacity());
|
||||||
MemoryUtil.memCopy(src, indexBuffer);
|
MemoryUtil.memCopy(src, indexBuffer);
|
||||||
eboSupplier = () -> {
|
eboSupplier = () -> {
|
||||||
|
int vbo = GL32.glGenBuffers();
|
||||||
|
|
||||||
MappedGlBuffer vbo = new MappedGlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER, GlBufferUsage.STATIC_DRAW);
|
// XXX ARRAY_BUFFER is bound and restored
|
||||||
|
var bufferType = GlBufferType.ARRAY_BUFFER;
|
||||||
vbo.upload(indexBuffer);
|
var oldBuffer = bufferType.getBoundBuffer();
|
||||||
|
bufferType.bind(vbo);
|
||||||
|
GL15.glBufferData(bufferType.glEnum, indexBuffer, GlBufferUsage.STATIC_DRAW.glEnum);
|
||||||
|
bufferType.bind(oldBuffer);
|
||||||
|
MemoryUtil.memFree(indexBuffer);
|
||||||
|
|
||||||
return new ElementBuffer(vbo, drawState.indexCount(), drawState.indexType());
|
return new ElementBuffer(vbo, drawState.indexCount(), drawState.indexType());
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,6 +45,7 @@ public interface Model {
|
||||||
return Formats.POS_TEX_NORMAL;
|
return Formats.POS_TEX_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX Since this is public API (technically) we cannot make assumptions about what GL state this method can use or modify unless a contract is established.
|
||||||
/**
|
/**
|
||||||
* Create an element buffer object that indexes the vertices of this model.
|
* Create an element buffer object that indexes the vertices of this model.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue