From 6227e81066630f77c4699bc0d691b57dce4e0600 Mon Sep 17 00:00:00 2001 From: JozsefA Date: Sun, 16 May 2021 15:39:52 -0700 Subject: [PATCH] TemplateBuffer is no more - Instead, BufferBuilderReader can decode parts of a BufferBuilder. - BufferedModel and its subclasses are now created directly with a ByteBuffer. - ContraptionModel renamed to IndexedModel. - InstancedModel and IndexedModel both now take model formats as arguments. - All of this allows for better abstraction, composition, and control of models rendered with Flywheel. --- .../backend/{ => core}/BufferedModel.java | 33 ++--- .../flywheel/backend/core/IndexedModel.java | 69 ++++++++++ .../flywheel/backend/gl/buffer/GlBuffer.java | 2 +- .../backend/gl/buffer/MappedBuffer.java | 6 + .../backend/instancing/InstancedModel.java | 25 +--- .../backend/instancing/RenderMaterial.java | 31 ++++- .../flywheel/util/BufferBuilderReader.java | 106 +++++++++++++++ .../render/ContraptionModel.java | 101 --------------- .../render/RenderedContraption.java | 121 +++++++++++++----- .../foundation/render/SuperByteBuffer.java | 57 ++++----- .../foundation/render/TemplateBuffer.java | 101 --------------- 11 files changed, 340 insertions(+), 312 deletions(-) rename src/main/java/com/jozufozu/flywheel/backend/{ => core}/BufferedModel.java (69%) create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/IndexedModel.java create mode 100644 src/main/java/com/jozufozu/flywheel/util/BufferBuilderReader.java delete mode 100644 src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionModel.java delete mode 100644 src/main/java/com/simibubi/create/foundation/render/TemplateBuffer.java diff --git a/src/main/java/com/jozufozu/flywheel/backend/BufferedModel.java b/src/main/java/com/jozufozu/flywheel/backend/core/BufferedModel.java similarity index 69% rename from src/main/java/com/jozufozu/flywheel/backend/BufferedModel.java rename to src/main/java/com/jozufozu/flywheel/backend/core/BufferedModel.java index 934ba2722..28825202c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/BufferedModel.java +++ b/src/main/java/com/jozufozu/flywheel/backend/core/BufferedModel.java @@ -1,33 +1,35 @@ -package com.jozufozu.flywheel.backend; +package com.jozufozu.flywheel.backend.core; + +import java.nio.ByteBuffer; -import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL20; +import com.jozufozu.flywheel.backend.RenderWork; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; -import com.simibubi.create.foundation.render.TemplateBuffer; -import net.minecraft.client.renderer.BufferBuilder; - -public abstract class BufferedModel extends TemplateBuffer { +public abstract class BufferedModel { + protected final ByteBuffer data; protected final VertexFormat modelFormat; + protected final int vertexCount; protected GlBuffer modelVBO; private boolean initialized; // lazy init private boolean removed; - protected BufferedModel(VertexFormat modelFormat, BufferBuilder buf) { - super(buf); + protected BufferedModel(VertexFormat modelFormat, ByteBuffer data, int vertices) { + this.data = data; this.modelFormat = modelFormat; + this.vertexCount = vertices; } /** * Renders this model, checking first if there is anything to render. */ public final void render() { - if (vertexCount == 0 || removed) return; + if (vertexCount <= 0 || removed) return; if (!initialized) { // Lazily acquire resources in order to get around initialization order, as #getTotalShaderAttributeCount @@ -60,22 +62,15 @@ public abstract class BufferedModel extends TemplateBuffer { } protected void initModel() { - int stride = modelFormat.getStride(); - int invariantSize = vertexCount * stride; - // allocate the buffer on the gpu - GL15.glBufferData(GL15.GL_ARRAY_BUFFER, invariantSize, GL15.GL_STATIC_DRAW); + modelVBO.alloc(data.capacity()); // mirror it in system memory so we can write to it - MappedBuffer buffer = modelVBO.getBuffer(0, invariantSize); - for (int i = 0; i < vertexCount; i++) { - copyVertex(buffer, i); - } + MappedBuffer buffer = modelVBO.getBuffer(0, data.capacity()); + buffer.put(data); buffer.flush(); } - protected abstract void copyVertex(MappedBuffer to, int index); - protected int getTotalShaderAttributeCount() { return modelFormat.getShaderAttributeCount(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/IndexedModel.java b/src/main/java/com/jozufozu/flywheel/backend/core/IndexedModel.java new file mode 100644 index 000000000..1372a13ca --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/IndexedModel.java @@ -0,0 +1,69 @@ +package com.jozufozu.flywheel.backend.core; + +import java.nio.ByteBuffer; + +import org.lwjgl.opengl.GL20; + +import com.jozufozu.flywheel.backend.gl.GlPrimitiveType; +import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; +import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; +import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; +import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; + +public class IndexedModel extends BufferedModel { + + protected GlPrimitiveType eboIndexType; + protected GlBuffer ebo; + + public IndexedModel(VertexFormat modelFormat, ByteBuffer buf, int vertices) { + super(modelFormat, buf, vertices); + } + + @Override + protected void init() { + super.init(); + + createEBO(); + } + + @Override + protected void doRender() { + modelVBO.bind(); + ebo.bind(); + + setupAttributes(); + GL20.glDrawElements(GL20.GL_QUADS, vertexCount, eboIndexType.getGlConstant(), 0); + + int numAttributes = getTotalShaderAttributeCount(); + for (int i = 0; i <= numAttributes; i++) { + GL20.glDisableVertexAttribArray(i); + } + + ebo.unbind(); + modelVBO.unbind(); + } + + protected final void createEBO() { + ebo = new GlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER); + eboIndexType = GlPrimitiveType.UINT; // TODO: choose this based on the number of vertices + + int indicesSize = vertexCount * eboIndexType.getSize(); + + ebo.bind(); + + ebo.alloc(indicesSize); + MappedBuffer indices = ebo.getBuffer(0, indicesSize); + for (int i = 0; i < vertexCount; i++) { + indices.putInt(i); + } + indices.flush(); + + ebo.unbind(); + } + + @Override + protected void deleteInternal() { + super.deleteInternal(); + ebo.delete(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java index c3c2da51a..4430fa76d 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java @@ -48,7 +48,7 @@ public class GlBuffer extends GlObject { } public MappedBuffer getBuffer(int offset, int length) { - if (Backend.compat.mapBufferRange == MapBufferRange.UNSUPPORTED) { + if (Backend.compat.mapBufferRange != MapBufferRange.UNSUPPORTED) { return new MappedBufferRange(this, offset, length, GL30.GL_MAP_WRITE_BIT); } else { MappedFullBuffer fullBuffer = new MappedFullBuffer(this, MappedBufferUsage.WRITE_ONLY); diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBuffer.java index 16de2eb1e..f8ee93fdc 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBuffer.java @@ -80,6 +80,12 @@ public abstract class MappedBuffer implements AutoCloseable { return this; } + public MappedBuffer put(ByteBuffer b) { + checkAndMap(); + internal.put(b); + return this; + } + public MappedBuffer putVec4(float x, float y, float z, float w) { checkAndMap(); internal.putFloat(x); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedModel.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedModel.java index 9409e4edf..a70108cbe 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedModel.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedModel.java @@ -1,24 +1,21 @@ package com.jozufozu.flywheel.backend.instancing; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.BitSet; import org.lwjgl.opengl.GL11; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.BufferedModel; -import com.jozufozu.flywheel.backend.core.materials.ModelAttributes; +import com.jozufozu.flywheel.backend.core.BufferedModel; import com.jozufozu.flywheel.backend.gl.GlVertexArray; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; -import net.minecraft.client.renderer.BufferBuilder; - public class InstancedModel extends BufferedModel { - public static final VertexFormat FORMAT = VertexFormat.builder().addAttributes(ModelAttributes.class).build(); public final InstancedTileRenderer renderer; @@ -34,8 +31,8 @@ public class InstancedModel extends BufferedModel { boolean anyToRemove; boolean anyToUpdate; - public InstancedModel(InstancedTileRenderer renderer, VertexFormat instanceFormat, InstanceFactory factory, BufferBuilder buf) { - super(FORMAT, buf); + public InstancedModel(VertexFormat modelFormat, ByteBuffer buf, int vertices, InstancedTileRenderer renderer, VertexFormat instanceFormat, InstanceFactory factory) { + super(modelFormat, buf, vertices); this.factory = factory; this.instanceFormat = instanceFormat; this.renderer = renderer; @@ -225,20 +222,6 @@ public class InstancedModel extends BufferedModel { } - @Override - protected void copyVertex(MappedBuffer constant, int i) { - constant.putFloat(getX(template, i)); - constant.putFloat(getY(template, i)); - constant.putFloat(getZ(template, i)); - - constant.put(getNX(template, i)); - constant.put(getNY(template, i)); - constant.put(getNZ(template, i)); - - constant.putFloat(getU(template, i)); - constant.putFloat(getV(template, i)); - } - protected int getTotalShaderAttributeCount() { return instanceFormat.getShaderAttributeCount() + super.getTotalShaderAttributeCount(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderMaterial.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderMaterial.java index 7ce543169..19f0c8fcb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderMaterial.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderMaterial.java @@ -1,5 +1,7 @@ package com.jozufozu.flywheel.backend.instancing; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.Arrays; import java.util.concurrent.ExecutionException; import java.util.function.Consumer; @@ -12,7 +14,10 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.jozufozu.flywheel.backend.core.BasicProgram; import com.jozufozu.flywheel.backend.core.PartialModel; +import com.jozufozu.flywheel.backend.core.materials.ModelAttributes; +import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.backend.gl.shader.ShaderCallback; +import com.jozufozu.flywheel.util.BufferBuilderReader; import com.jozufozu.flywheel.util.RenderUtil; import com.jozufozu.flywheel.util.VirtualEmptyModelData; import com.mojang.blaze3d.matrix.MatrixStack; @@ -31,6 +36,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Matrix4f; public class RenderMaterial

{ + public static final VertexFormat MODEL_FORMAT = VertexFormat.builder().addAttributes(ModelAttributes.class).build(); protected final InstancedTileRenderer

renderer; protected final Cache> models; @@ -113,9 +119,30 @@ public class RenderMaterial

{ } private InstancedModel buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) { - BufferBuilder builder = getBufferBuilder(model, referenceState, ms); + BufferBuilderReader reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms)); - return new InstancedModel<>(renderer, spec.getInstanceFormat(), spec.getInstanceFactory(), builder); + VertexFormat format = MODEL_FORMAT; + int vertexCount = reader.getVertexCount(); + + ByteBuffer to = ByteBuffer.allocate(vertexCount * format.getStride()); + to.order(ByteOrder.nativeOrder()); + + for (int i = 0; i < vertexCount; i++) { + to.putFloat(reader.getX(i)); + to.putFloat(reader.getY(i)); + to.putFloat(reader.getZ(i)); + + to.put(reader.getNX(i)); + to.put(reader.getNY(i)); + to.put(reader.getNZ(i)); + + to.putFloat(reader.getU(i)); + to.putFloat(reader.getV(i)); + } + + to.rewind(); + + return new InstancedModel<>(format, to, vertexCount, renderer, spec.getInstanceFormat(), spec.getInstanceFactory()); } private static final Direction[] dirs; diff --git a/src/main/java/com/jozufozu/flywheel/util/BufferBuilderReader.java b/src/main/java/com/jozufozu/flywheel/util/BufferBuilderReader.java new file mode 100644 index 000000000..15a6e1390 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/BufferBuilderReader.java @@ -0,0 +1,106 @@ +package com.jozufozu.flywheel.util; + +import java.nio.ByteBuffer; + +import com.mojang.datafixers.util.Pair; + +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.vertex.VertexFormat; + +public class BufferBuilderReader { + + private final ByteBuffer buffer; + private final int vertexCount; + private final int formatSize; + private final int size; + + public BufferBuilderReader(BufferBuilder builder) { + VertexFormat vertexFormat = builder.getVertexFormat(); + Pair data = builder.popData(); + buffer = data.getSecond(); + + formatSize = vertexFormat.getSize(); + + vertexCount = data.getFirst() + .getCount(); + + size = vertexCount * formatSize; + + // TODO: adjust the getters based on the input format +// ImmutableList elements = vertexFormat.getElements(); +// for (int i = 0, size = elements.size(); i < size; i++) { +// VertexFormatElement element = elements.get(i); +// int offset = vertexFormat.getOffset(i); +// +// element.getUsage() +// } + } + + public boolean isEmpty() { + return vertexCount == 0; + } + + public int vertIdx(int vertexIndex) { + return vertexIndex * formatSize; + } + + public float getX(int index) { + return buffer.getFloat(vertIdx(index)); + } + + public float getY(int index) { + return buffer.getFloat(vertIdx(index) + 4); + } + + public float getZ(int index) { + return buffer.getFloat(vertIdx(index) + 8); + } + + public byte getR(int index) { + return buffer.get(vertIdx(index) + 12); + } + + public byte getG(int index) { + return buffer.get(vertIdx(index) + 13); + } + + public byte getB(int index) { + return buffer.get(vertIdx(index) + 14); + } + + public byte getA(int index) { + return buffer.get(vertIdx(index) + 15); + } + + public float getU(int index) { + return buffer.getFloat(vertIdx(index) + 16); + } + + public float getV(int index) { + return buffer.getFloat(vertIdx(index) + 20); + } + + public int getLight(int index) { + return buffer.getInt(vertIdx(index) + 24); + } + + public byte getNX(int index) { + return buffer.get(vertIdx(index) + 28); + } + + public byte getNY(int index) { + return buffer.get(vertIdx(index) + 29); + } + + public byte getNZ(int index) { + return buffer.get(vertIdx(index) + 30); + } + + public int getVertexCount() { + return vertexCount; + } + + public int getSize() { + return size; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionModel.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionModel.java deleted file mode 100644 index acdca2f9f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionModel.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; - -import org.lwjgl.opengl.GL20; - -import com.jozufozu.flywheel.backend.BufferedModel; -import com.jozufozu.flywheel.backend.gl.GlPrimitiveType; -import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; -import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; -import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; -import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; - -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.LightTexture; - -public class ContraptionModel extends BufferedModel { - public static final VertexFormat FORMAT = VertexFormat.builder() - .addAttributes(ContraptionAttributes.class) - .build(); - - protected GlPrimitiveType eboIndexType; - protected GlBuffer ebo; - - public ContraptionModel(BufferBuilder buf) { - super(FORMAT, buf); - } - - @Override - protected void init() { - super.init(); - - createEBO(); - } - - @Override - protected void doRender() { - modelVBO.bind(); - ebo.bind(); - - setupAttributes(); - GL20.glDrawElements(GL20.GL_QUADS, vertexCount, eboIndexType.getGlConstant(), 0); - - int numAttributes = getTotalShaderAttributeCount(); - for (int i = 0; i <= numAttributes; i++) { - GL20.glDisableVertexAttribArray(i); - } - - ebo.unbind(); - modelVBO.unbind(); - } - - protected final void createEBO() { - ebo = new GlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER); - eboIndexType = GlPrimitiveType.UINT; // TODO: choose this based on the number of vertices - - int indicesSize = vertexCount * eboIndexType.getSize(); - - ebo.bind(); - - ebo.alloc(indicesSize); - MappedBuffer indices = ebo.getBuffer(0, indicesSize); - for (int i = 0; i < vertexCount; i++) { - indices.putInt(i); - } - indices.flush(); - - ebo.unbind(); - } - - @Override - protected void copyVertex(MappedBuffer to, int vertex) { - to.putFloat(getX(template, vertex)); - to.putFloat(getY(template, vertex)); - to.putFloat(getZ(template, vertex)); - - to.put(getNX(template, vertex)); - to.put(getNY(template, vertex)); - to.put(getNZ(template, vertex)); - - to.putFloat(getU(template, vertex)); - to.putFloat(getV(template, vertex)); - - to.put(getR(template, vertex)); - to.put(getG(template, vertex)); - to.put(getB(template, vertex)); - to.put(getA(template, vertex)); - - int light = getLight(template, vertex); - - byte block = (byte) (LightTexture.getBlockLightCoordinates(light) << 4); - byte sky = (byte) (LightTexture.getSkyLightCoordinates(light) << 4); - - to.put(block); - to.put(sky); - } - - @Override - protected void deleteInternal() { - super.deleteInternal(); - ebo.delete(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java index d847b9cd8..079ae0524 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java @@ -1,16 +1,23 @@ package com.simibubi.create.content.contraptions.components.structureMovement.render; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; +import javax.annotation.Nullable; + import org.lwjgl.opengl.GL11; import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.core.IndexedModel; +import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; import com.jozufozu.flywheel.backend.light.GridAlignedBB; +import com.jozufozu.flywheel.util.BufferBuilderReader; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; @@ -25,6 +32,7 @@ import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.BlockModelRenderer; import net.minecraft.client.renderer.BlockModelShapes; import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderTypeLookup; import net.minecraft.client.renderer.texture.OverlayTexture; @@ -40,17 +48,21 @@ import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.client.model.data.EmptyModelData; public class RenderedContraption { - private static final BlockModelRenderer MODEL_RENDERER = new BlockModelRenderer(Minecraft.getInstance().getBlockColors()); - private static final BlockModelShapes BLOCK_MODELS = Minecraft.getInstance().getModelManager().getBlockModelShapes(); + public static final VertexFormat FORMAT = VertexFormat.builder() + .addAttributes(ContraptionAttributes.class) + .build(); - public Contraption contraption; - private final ContraptionLighter lighter; - public final ContraptionKineticRenderer kinetics; - public final PlacementSimulationWorld renderWorld; + private static final BlockModelRenderer MODEL_RENDERER = new BlockModelRenderer(Minecraft.getInstance().getBlockColors()); + private static final BlockModelShapes BLOCK_MODELS = Minecraft.getInstance().getModelManager().getBlockModelShapes(); - private final Map renderLayers = new HashMap<>(); + public Contraption contraption; + private final ContraptionLighter lighter; + public final ContraptionKineticRenderer kinetics; + public final PlacementSimulationWorld renderWorld; - private Matrix4f model; + private final Map renderLayers = new HashMap<>(); + + private Matrix4f model; private AxisAlignedBB lightBox; public RenderedContraption(World world, Contraption contraption) { @@ -79,7 +91,7 @@ public class RenderedContraption { } public void doRenderLayer(RenderType layer, ContraptionProgram shader) { - ContraptionModel structure = renderLayers.get(layer); + IndexedModel structure = renderLayers.get(layer); if (structure != null) { setup(shader); structure.render(); @@ -120,9 +132,9 @@ public class RenderedContraption { } void invalidate() { - for (ContraptionModel buffer : renderLayers.values()) { - buffer.delete(); - } + for (IndexedModel buffer : renderLayers.values()) { + buffer.delete(); + } renderLayers.clear(); lighter.lightVolume.delete(); @@ -131,17 +143,18 @@ public class RenderedContraption { } private void buildLayers() { - for (ContraptionModel buffer : renderLayers.values()) { - buffer.delete(); - } + for (IndexedModel buffer : renderLayers.values()) { + buffer.delete(); + } renderLayers.clear(); List blockLayers = RenderType.getBlockLayers(); for (RenderType layer : blockLayers) { - renderLayers.put(layer, buildStructureModel(renderWorld, contraption, layer)); - } + IndexedModel layerModel = buildStructureModel(renderWorld, contraption, layer); + if (layerModel != null) renderLayers.put(layer, layerModel); + } } private void buildInstancedTiles() { @@ -153,29 +166,67 @@ public class RenderedContraption { BlockPos pos = te.getPos(); te.setLocation(renderWorld, pos); kinetics.add(te); - te.setLocation(world, pos); - } - } - } - } + te.setLocation(world, pos); + } + } + } + } - private void buildActors() { - contraption.getActors().forEach(kinetics::createActor); - } + private void buildActors() { + contraption.getActors().forEach(kinetics::createActor); + } - private static ContraptionModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { - BufferBuilder builder = buildStructure(renderWorld, c, layer); - return new ContraptionModel(builder); - } + @Nullable + private static IndexedModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { + BufferBuilderReader reader = new BufferBuilderReader(buildStructure(renderWorld, c, layer)); - private static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) { - PlacementSimulationWorld renderWorld = new PlacementSimulationWorld(world); + int vertexCount = reader.getVertexCount(); + if (vertexCount == 0) return null; - renderWorld.setTileEntities(c.presentTileEntities.values()); + VertexFormat format = FORMAT; - for (Template.BlockInfo info : c.getBlocks() - .values()) - // Skip individual lighting updates to prevent lag with large contraptions + ByteBuffer to = ByteBuffer.allocate(format.getStride() * vertexCount); + to.order(ByteOrder.nativeOrder()); + + for (int i = 0; i < vertexCount; i++) { + to.putFloat(reader.getX(i)); + to.putFloat(reader.getY(i)); + to.putFloat(reader.getZ(i)); + + to.put(reader.getNX(i)); + to.put(reader.getNY(i)); + to.put(reader.getNZ(i)); + + to.putFloat(reader.getU(i)); + to.putFloat(reader.getV(i)); + + to.put(reader.getR(i)); + to.put(reader.getG(i)); + to.put(reader.getB(i)); + to.put(reader.getA(i)); + + int light = reader.getLight(i); + + byte block = (byte) (LightTexture.getBlockLightCoordinates(light) << 4); + byte sky = (byte) (LightTexture.getSkyLightCoordinates(light) << 4); + + to.put(block); + to.put(sky); + } + + to.rewind(); + + return new IndexedModel(format, to, vertexCount); + } + + private static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) { + PlacementSimulationWorld renderWorld = new PlacementSimulationWorld(world); + + renderWorld.setTileEntities(c.presentTileEntities.values()); + + for (Template.BlockInfo info : c.getBlocks() + .values()) + // Skip individual lighting updates to prevent lag with large contraptions renderWorld.setBlockState(info.pos, info.state, 128); renderWorld.updateLightSources(); diff --git a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java index f3ff7ef80..94fbde2ab 100644 --- a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java @@ -1,8 +1,6 @@ package com.simibubi.create.foundation.render; -import java.nio.Buffer; -import java.nio.ByteBuffer; - +import com.jozufozu.flywheel.util.BufferBuilderReader; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; @@ -26,12 +24,9 @@ import net.minecraft.world.LightType; import net.minecraft.world.World; import net.minecraftforge.client.model.pipeline.LightUtil; -public class SuperByteBuffer extends TemplateBuffer { - - public interface IVertexLighter { - public int getPackedLight(float x, float y, float z); - } +public class SuperByteBuffer { + private final BufferBuilderReader template; // Vertex Position private MatrixStack transforms; @@ -49,7 +44,7 @@ public class SuperByteBuffer extends TemplateBuffer { private int r, g, b, a; public SuperByteBuffer(BufferBuilder buf) { - super(buf); + template = new BufferBuilderReader(buf); transforms = new MatrixStack(); } @@ -70,22 +65,20 @@ public class SuperByteBuffer extends TemplateBuffer { Vector4f lightPos = new Vector4f(); public void renderInto(MatrixStack input, IVertexBuilder builder) { - ByteBuffer buffer = template; - if (((Buffer) buffer).limit() == 0) + if (isEmpty()) return; - ((Buffer) buffer).rewind(); Matrix3f normalMat = transforms.peek() - .getNormal() - .copy(); + .getNormal() + .copy(); // normalMat.multiply(transforms.peek().getNormal()); Matrix4f modelMat = input.peek() - .getModel() - .copy(); + .getModel() + .copy(); Matrix4f localTransforms = transforms.peek() - .getModel(); + .getModel(); modelMat.multiply(localTransforms); if (shouldLight && lightTransform != null) { @@ -94,18 +87,18 @@ public class SuperByteBuffer extends TemplateBuffer { } float f = .5f; - int vertexCount = vertexCount(buffer); + int vertexCount = template.getVertexCount(); for (int i = 0; i < vertexCount; i++) { - float x = getX(buffer, i); - float y = getY(buffer, i); - float z = getZ(buffer, i); - byte r = getR(buffer, i); - byte g = getG(buffer, i); - byte b = getB(buffer, i); - byte a = getA(buffer, i); - float normalX = getNX(buffer, i) / 127f; - float normalY = getNY(buffer, i) / 127f; - float normalZ = getNZ(buffer, i) / 127f; + float x = template.getX(i); + float y = template.getY(i); + float z = template.getZ(i); + byte r = template.getR(i); + byte g = template.getG(i); + byte b = template.getB(i); + byte a = template.getA(i); + float normalX = template.getNX(i) / 127f; + float normalY = template.getNY(i) / 127f; + float normalZ = template.getNZ(i) / 127f; float staticDiffuse = LightUtil.diffuseLight(normalX, normalY, normalZ); normal.set(normalX, normalY, normalZ); @@ -134,8 +127,8 @@ public class SuperByteBuffer extends TemplateBuffer { builder.color(colorR, colorG, colorB, a); } - float u = getU(buffer, i); - float v = getV(buffer, i); + float u = template.getU(i); + float v = template.getV(i); if (spriteShiftFunc != null) { spriteShiftFunc.shift(builder, u, v); @@ -156,7 +149,7 @@ public class SuperByteBuffer extends TemplateBuffer { } builder.light(light); } else - builder.light(getLight(buffer, i)); + builder.light(template.getLight(i)); builder.normal(nx, ny, nz) .endVertex(); @@ -297,7 +290,7 @@ public class SuperByteBuffer extends TemplateBuffer { } public boolean isEmpty() { - return ((Buffer) template).limit() == 0; + return template.isEmpty(); } @FunctionalInterface diff --git a/src/main/java/com/simibubi/create/foundation/render/TemplateBuffer.java b/src/main/java/com/simibubi/create/foundation/render/TemplateBuffer.java deleted file mode 100644 index 5f3eef7b5..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/TemplateBuffer.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.simibubi.create.foundation.render; - -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import com.mojang.datafixers.util.Pair; - -import net.minecraft.client.renderer.BufferBuilder; - -public class TemplateBuffer { - protected ByteBuffer template; - protected int formatSize; - protected int vertexCount; - - public TemplateBuffer() { - - } - - public TemplateBuffer(BufferBuilder buf) { - Pair state = buf.popData(); - ByteBuffer rendered = state.getSecond(); - rendered.order(ByteOrder.nativeOrder()); // Vanilla bug, endianness does not carry over into sliced buffers - - formatSize = buf.getVertexFormat() - .getSize(); - vertexCount = state.getFirst() - .getCount(); - int size = vertexCount * formatSize; - - template = ByteBuffer.allocate(size); - template.order(rendered.order()); - ((Buffer) template).limit(((Buffer) rendered).limit()); - template.put(rendered); - ((Buffer) template).rewind(); - } - - public boolean isEmpty() { - return ((Buffer) template).limit() == 0; - } - - protected int vertexCount(ByteBuffer buffer) { - return ((Buffer) buffer).limit() / formatSize; - } - - protected int getBufferPosition(int vertexIndex) { - return vertexIndex * formatSize; - } - - protected float getX(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index)); - } - - protected float getY(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index) + 4); - } - - protected float getZ(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index) + 8); - } - - protected byte getR(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 12); - } - - protected byte getG(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 13); - } - - protected byte getB(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 14); - } - - protected byte getA(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 15); - } - - protected float getU(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index) + 16); - } - - protected float getV(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index) + 20); - } - - protected int getLight(ByteBuffer buffer, int index) { - return buffer.getInt(getBufferPosition(index) + 24); - } - - protected byte getNX(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 28); - } - - protected byte getNY(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 29); - } - - protected byte getNZ(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 30); - } -}