From f564ce1a33707eb65ad37093d5e9571b1c4b3b93 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Thu, 10 Sep 2020 23:37:14 +0200 Subject: [PATCH] The Buffer Kerfuffle - Refactored animated bytebuffers - Fixed animated buffers bleeding vertices and rendering inconsitently when switching from/to optifine shaders --- .../crafter/MechanicalCrafterRenderer.java | 4 +- .../relays/belt/BeltRenderer.java | 4 +- .../foundation/utility/SuperByteBuffer.java | 216 +++++++----------- .../utility/SuperByteBufferCache.java | 13 +- 4 files changed, 89 insertions(+), 148 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterRenderer.java index 260f344c7..69caac6d9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterRenderer.java @@ -179,9 +179,7 @@ public class MechanicalCrafterRenderer extends SafeTileEntityRenderer { textureIndex += cycleLength; beltBuffer.shiftUVtoSheet(spriteShift, (textureIndex % 4) / 4f, (textureIndex / 4) / 4f, 4); - } else { - beltBuffer.dontShiftUV(); - } + } beltBuffer.renderInto(ms, vb); diff --git a/src/main/java/com/simibubi/create/foundation/utility/SuperByteBuffer.java b/src/main/java/com/simibubi/create/foundation/utility/SuperByteBuffer.java index c888ea1d2..ce9c01c80 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/SuperByteBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/utility/SuperByteBuffer.java @@ -15,7 +15,6 @@ import net.minecraft.client.renderer.GLAllocation; import net.minecraft.client.renderer.Matrix4f; import net.minecraft.client.renderer.Vector4f; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.world.LightType; @@ -27,16 +26,14 @@ public class SuperByteBuffer { public int getPackedLight(float x, float y, float z); } - public static final int FORMAT_LENGTH = DefaultVertexFormats.BLOCK.getSize(); - protected ByteBuffer original; - protected ByteBuffer mutable; + protected ByteBuffer template; + protected int formatSize; // Vertex Position private MatrixStack transforms; // Vertex Texture Coords private boolean shouldShiftUV; - private boolean resetUV; private SpriteShiftEntry spriteShift; private float uTarget, vTarget; @@ -52,81 +49,23 @@ public class SuperByteBuffer { public SuperByteBuffer(BufferBuilder buf) { Pair state = buf.popData(); - ByteBuffer original = state.getSecond(); - original.order(ByteOrder.nativeOrder()); // Vanilla bug, endianness does not carry over into sliced buffers - this.original = original; - this.mutable = GLAllocation.createDirectByteBuffer(state.getFirst() - .getCount() - * buf.getVertexFormat() - .getSize()); - this.mutable.order(original.order()); - this.mutable.limit(original.limit()); - mutable.put(this.original); - mutable.rewind(); + ByteBuffer rendered = state.getSecond(); + rendered.order(ByteOrder.nativeOrder()); // Vanilla bug, endianness does not carry over into sliced buffers + + formatSize = buf.getVertexFormat() + .getSize(); + int size = state.getFirst() + .getCount() * formatSize; + + template = GLAllocation.createDirectByteBuffer(size); + template.order(rendered.order()); + template.limit(rendered.limit()); + template.put(rendered); + template.rewind(); transforms = new MatrixStack(); } - public ByteBuffer build(MatrixStack view) { - original.rewind(); - mutable.rewind(); - - Matrix4f t = view.peek() - .getModel() - .copy(); - Matrix4f localTransforms = transforms.peek() - .getModel(); - - t.multiply(localTransforms); - - for (int vertex = 0; vertex < vertexCount(original); vertex++) { - Vector4f pos = new Vector4f(getX(original, vertex), getY(original, vertex), getZ(original, vertex), 1F); - Vector4f lightPos = new Vector4f(pos.getX(), pos.getY(), pos.getZ(), pos.getW()); - - pos.transform(t); - lightPos.transform(localTransforms); - putPos(mutable, vertex, pos.getX(), pos.getY(), pos.getZ()); - - if (shouldColor) { - byte lumByte = getR(original, vertex); - float lum = (lumByte < 0 ? 255 + lumByte : lumByte) / 256f; - int r2 = (int) (r * lum); - int g2 = (int) (g * lum); - int b2 = (int) (b * lum); - putColor(mutable, vertex, (byte) r2, (byte) g2, (byte) b2, (byte) a); - } - - if (shouldShiftUV) { - float u = getU(original, vertex); - float v = getV(original, vertex); - float targetU = spriteShift.getTarget() - .getInterpolatedU((getUnInterpolatedU(spriteShift.getOriginal(), u) / sheetSize) + uTarget * 16); - float targetV = spriteShift.getTarget() - .getInterpolatedV((getUnInterpolatedV(spriteShift.getOriginal(), v) / sheetSize) + vTarget * 16); - putUV(mutable, vertex, targetU, targetV); - } - - if (resetUV) - putUV(mutable, vertex, getU(original, vertex), getV(original, vertex)); - - if (shouldLight) { - int light = packedLightCoords; - if (lightTransform != null) { - lightPos.transform(lightTransform); - light = getLight(Minecraft.getInstance().world, lightPos); - } - putLight(mutable, vertex, light); - } - } - - transforms = new MatrixStack(); - shouldShiftUV = false; - shouldColor = false; - shouldLight = false; - mutable.rewind(); - return mutable; - } - public static float getUnInterpolatedU(TextureAtlasSprite sprite, float u) { float f = sprite.getMaxU() - sprite.getMinU(); return (u - sprite.getMinU()) / f * 16.0F; @@ -137,31 +76,72 @@ public class SuperByteBuffer { return (v - sprite.getMinV()) / f * 16.0F; } - public void renderInto(MatrixStack input, IVertexBuilder buffer) { - if (original.limit() == 0) + public void renderInto(MatrixStack input, IVertexBuilder builder) { + ByteBuffer buffer = template; + if (buffer.limit() == 0) return; - if (!(buffer instanceof BufferBuilder)) { - Matrix4f t = input.peek() - .getModel() - .copy(); - Matrix4f localTransforms = transforms.peek() - .getModel(); - t.multiply(localTransforms); + buffer.rewind(); - ByteBuffer m = mutable; - for (int v = 0; v < vertexCount(m); v++) { - Vector4f pos = new Vector4f(getX(original, v), getY(original, v), getZ(original, v), 1F); - pos.transform(t); - buffer.vertex(pos.getX(), pos.getY(), pos.getZ()) - .color(getR(m, v), getG(m, v), getB(m, v), getA(m, v)) - .texture(getU(m, v), getV(m, v)) - .light(getLight(m, v)) - .normal(getNX(m, v), getNY(m, v), getNZ(m, v)) - .endVertex(); - } - transforms = new MatrixStack(); - } else - ((BufferBuilder) buffer).putBulkData(build(input)); + Matrix4f t = input.peek() + .getModel() + .copy(); + Matrix4f localTransforms = transforms.peek() + .getModel(); + t.multiply(localTransforms); + + for (int i = 0; i < vertexCount(buffer); i++) { + float x = getX(buffer, i); + float y = getY(buffer, i); + float z = getZ(buffer, i); + + Vector4f pos = new Vector4f(x, y, z, 1F); + Vector4f lightPos = new Vector4f(x, y, z, 1F); + pos.transform(t); + lightPos.transform(localTransforms); + + builder.vertex(pos.getX(), pos.getY(), pos.getZ()); + + byte r = getR(buffer, i); + byte g = getG(buffer, i); + byte b = getB(buffer, i); + byte a = getA(buffer, i); + + if (shouldColor) { + float lum = (r < 0 ? 255 + r : r) / 256f; + builder.color((int) (this.r * lum), (int) (this.g * lum), (int) (this.b * lum), this.a); + } else + builder.color(r, g, b, a); + + float u = getU(buffer, i); + float v = getV(buffer, i); + + if (shouldShiftUV) { + float targetU = spriteShift.getTarget() + .getInterpolatedU((getUnInterpolatedU(spriteShift.getOriginal(), u) / sheetSize) + uTarget * 16); + float targetV = spriteShift.getTarget() + .getInterpolatedV((getUnInterpolatedV(spriteShift.getOriginal(), v) / sheetSize) + vTarget * 16); + builder.texture(targetU, targetV); + } else + builder.texture(u, v); + + if (shouldLight) { + int light = packedLightCoords; + if (lightTransform != null) { + lightPos.transform(lightTransform); + light = getLight(Minecraft.getInstance().world, lightPos); + } + builder.light(light); + } else + builder.light(getLight(buffer, i)); + + builder.normal(getNX(buffer, i), getNY(buffer, i), getNZ(buffer, i)) + .endVertex(); + } + + transforms = new MatrixStack(); + shouldShiftUV = false; + shouldColor = false; + shouldLight = false; } public SuperByteBuffer translate(double x, double y, double z) { @@ -188,7 +168,6 @@ public class SuperByteBuffer { public SuperByteBuffer shiftUV(SpriteShiftEntry entry) { shouldShiftUV = true; - resetUV = false; spriteShift = entry; uTarget = 0; vTarget = 0; @@ -198,7 +177,6 @@ public class SuperByteBuffer { public SuperByteBuffer shiftUVtoSheet(SpriteShiftEntry entry, float uTarget, float vTarget, int sheetSize) { shouldShiftUV = true; - resetUV = false; spriteShift = entry; this.uTarget = uTarget; this.vTarget = vTarget; @@ -206,12 +184,6 @@ public class SuperByteBuffer { return this; } - public SuperByteBuffer dontShiftUV() { - shouldShiftUV = false; - resetUV = true; - return this; - } - public SuperByteBuffer light(int packedLightCoords) { shouldLight = true; lightTransform = null; @@ -235,11 +207,11 @@ public class SuperByteBuffer { } protected int vertexCount(ByteBuffer buffer) { - return buffer.limit() / FORMAT_LENGTH; + return buffer.limit() / formatSize; } protected int getBufferPosition(int vertexIndex) { - return vertexIndex * FORMAT_LENGTH; + return vertexIndex * formatSize; } protected float getX(ByteBuffer buffer, int index) { @@ -294,32 +266,6 @@ public class SuperByteBuffer { return buffer.get(getBufferPosition(index) + 30); } - protected void putPos(ByteBuffer buffer, int index, float x, float y, float z) { - int pos = getBufferPosition(index); - buffer.putFloat(pos, x); - buffer.putFloat(pos + 4, y); - buffer.putFloat(pos + 8, z); - } - - protected void putUV(ByteBuffer buffer, int index, float u, float v) { - int pos = getBufferPosition(index); - buffer.putFloat(pos + 16, u); - buffer.putFloat(pos + 20, v); - } - - protected void putLight(ByteBuffer buffer, int index, int packedLight) { - buffer.putShort(getBufferPosition(index) + 24, (short) (packedLight & 0xFF)); - buffer.putShort(getBufferPosition(index) + 26, (short) ((packedLight >> 16) & 0xFF)); - } - - protected void putColor(ByteBuffer buffer, int index, byte r, byte g, byte b, byte a) { - int bufferPosition = getBufferPosition(index); - buffer.put(bufferPosition + 12, r); - buffer.put(bufferPosition + 13, g); - buffer.put(bufferPosition + 14, b); - buffer.put(bufferPosition + 15, a); - } - private static int getLight(World world, Vector4f lightPos) { BlockPos.Mutable pos = new BlockPos.Mutable(); float sky = 0, block = 0; diff --git a/src/main/java/com/simibubi/create/foundation/utility/SuperByteBufferCache.java b/src/main/java/com/simibubi/create/foundation/utility/SuperByteBufferCache.java index 1e55fa6af..0a46c4c3a 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/SuperByteBufferCache.java +++ b/src/main/java/com/simibubi/create/foundation/utility/SuperByteBufferCache.java @@ -2,7 +2,6 @@ package com.simibubi.create.foundation.utility; import java.util.HashMap; import java.util.Map; -import java.util.Random; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; @@ -110,14 +109,14 @@ public class SuperByteBufferCache { } private SuperByteBuffer standardModelRender(IBakedModel model, BlockState referenceState, MatrixStack ms) { - BlockRendererDispatcher dispatcher = Minecraft.getInstance() - .getBlockRendererDispatcher(); + Minecraft mc = Minecraft.getInstance(); + BlockRendererDispatcher dispatcher = mc.getBlockRendererDispatcher(); BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); - BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize()); - Random random = new Random(); + BufferBuilder builder = new BufferBuilder(512); + builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - blockRenderer.renderModelFlat(Minecraft.getInstance().world, model, referenceState, BlockPos.ZERO.up(255), ms, - builder, true, random, 42, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE); + blockRenderer.renderModel(mc.world, model, referenceState, BlockPos.ZERO.up(255), ms, builder, true, + mc.world.rand, 42, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE); builder.finishDrawing(); return new SuperByteBuffer(builder);