The Buffer Kerfuffle

- Refactored animated bytebuffers
- Fixed animated buffers bleeding vertices and rendering inconsitently when switching from/to optifine shaders
This commit is contained in:
simibubi 2020-09-10 23:37:14 +02:00
parent 4325cef8dc
commit f564ce1a33
4 changed files with 89 additions and 148 deletions

View file

@ -179,8 +179,6 @@ public class MechanicalCrafterRenderer extends SafeTileEntityRenderer<Mechanical
if (te.phase == Phase.EXPORTING) { if (te.phase == Phase.EXPORTING) {
int textureIndex = (int) ((te.getCountDownSpeed() / 128f * AnimationTickHolder.ticks)); int textureIndex = (int) ((te.getCountDownSpeed() / 128f * AnimationTickHolder.ticks));
beltBuffer.shiftUVtoSheet(AllSpriteShifts.CRAFTER_THINGIES, (textureIndex % 4) / 4f, 0, 1); beltBuffer.shiftUVtoSheet(AllSpriteShifts.CRAFTER_THINGIES, (textureIndex % 4) / 4f, 0, 1);
} else {
beltBuffer.dontShiftUV();
} }
beltBuffer.renderInto(ms, vb); beltBuffer.renderInto(ms, vb);

View file

@ -109,8 +109,6 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
textureIndex += cycleLength; textureIndex += cycleLength;
beltBuffer.shiftUVtoSheet(spriteShift, (textureIndex % 4) / 4f, (textureIndex / 4) / 4f, 4); beltBuffer.shiftUVtoSheet(spriteShift, (textureIndex % 4) / 4f, (textureIndex / 4) / 4f, 4);
} else {
beltBuffer.dontShiftUV();
} }
beltBuffer.renderInto(ms, vb); beltBuffer.renderInto(ms, vb);

View file

@ -15,7 +15,6 @@ import net.minecraft.client.renderer.GLAllocation;
import net.minecraft.client.renderer.Matrix4f; import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.Vector4f; import net.minecraft.client.renderer.Vector4f;
import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.LightType; import net.minecraft.world.LightType;
@ -27,16 +26,14 @@ public class SuperByteBuffer {
public int getPackedLight(float x, float y, float z); public int getPackedLight(float x, float y, float z);
} }
public static final int FORMAT_LENGTH = DefaultVertexFormats.BLOCK.getSize(); protected ByteBuffer template;
protected ByteBuffer original; protected int formatSize;
protected ByteBuffer mutable;
// Vertex Position // Vertex Position
private MatrixStack transforms; private MatrixStack transforms;
// Vertex Texture Coords // Vertex Texture Coords
private boolean shouldShiftUV; private boolean shouldShiftUV;
private boolean resetUV;
private SpriteShiftEntry spriteShift; private SpriteShiftEntry spriteShift;
private float uTarget, vTarget; private float uTarget, vTarget;
@ -52,81 +49,23 @@ public class SuperByteBuffer {
public SuperByteBuffer(BufferBuilder buf) { public SuperByteBuffer(BufferBuilder buf) {
Pair<DrawState, ByteBuffer> state = buf.popData(); Pair<DrawState, ByteBuffer> state = buf.popData();
ByteBuffer original = state.getSecond(); ByteBuffer rendered = state.getSecond();
original.order(ByteOrder.nativeOrder()); // Vanilla bug, endianness does not carry over into sliced buffers rendered.order(ByteOrder.nativeOrder()); // Vanilla bug, endianness does not carry over into sliced buffers
this.original = original;
this.mutable = GLAllocation.createDirectByteBuffer(state.getFirst() formatSize = buf.getVertexFormat()
.getCount() .getSize();
* buf.getVertexFormat() int size = state.getFirst()
.getSize()); .getCount() * formatSize;
this.mutable.order(original.order());
this.mutable.limit(original.limit()); template = GLAllocation.createDirectByteBuffer(size);
mutable.put(this.original); template.order(rendered.order());
mutable.rewind(); template.limit(rendered.limit());
template.put(rendered);
template.rewind();
transforms = new MatrixStack(); 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) { public static float getUnInterpolatedU(TextureAtlasSprite sprite, float u) {
float f = sprite.getMaxU() - sprite.getMinU(); float f = sprite.getMaxU() - sprite.getMinU();
return (u - sprite.getMinU()) / f * 16.0F; return (u - sprite.getMinU()) / f * 16.0F;
@ -137,31 +76,72 @@ public class SuperByteBuffer {
return (v - sprite.getMinV()) / f * 16.0F; return (v - sprite.getMinV()) / f * 16.0F;
} }
public void renderInto(MatrixStack input, IVertexBuilder buffer) { public void renderInto(MatrixStack input, IVertexBuilder builder) {
if (original.limit() == 0) ByteBuffer buffer = template;
if (buffer.limit() == 0)
return; return;
if (!(buffer instanceof BufferBuilder)) { buffer.rewind();
Matrix4f t = input.peek()
.getModel()
.copy();
Matrix4f localTransforms = transforms.peek()
.getModel();
t.multiply(localTransforms);
ByteBuffer m = mutable; Matrix4f t = input.peek()
for (int v = 0; v < vertexCount(m); v++) { .getModel()
Vector4f pos = new Vector4f(getX(original, v), getY(original, v), getZ(original, v), 1F); .copy();
pos.transform(t); Matrix4f localTransforms = transforms.peek()
buffer.vertex(pos.getX(), pos.getY(), pos.getZ()) .getModel();
.color(getR(m, v), getG(m, v), getB(m, v), getA(m, v)) t.multiply(localTransforms);
.texture(getU(m, v), getV(m, v))
.light(getLight(m, v)) for (int i = 0; i < vertexCount(buffer); i++) {
.normal(getNX(m, v), getNY(m, v), getNZ(m, v)) float x = getX(buffer, i);
.endVertex(); float y = getY(buffer, i);
} float z = getZ(buffer, i);
transforms = new MatrixStack();
} else Vector4f pos = new Vector4f(x, y, z, 1F);
((BufferBuilder) buffer).putBulkData(build(input)); 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) { public SuperByteBuffer translate(double x, double y, double z) {
@ -188,7 +168,6 @@ public class SuperByteBuffer {
public SuperByteBuffer shiftUV(SpriteShiftEntry entry) { public SuperByteBuffer shiftUV(SpriteShiftEntry entry) {
shouldShiftUV = true; shouldShiftUV = true;
resetUV = false;
spriteShift = entry; spriteShift = entry;
uTarget = 0; uTarget = 0;
vTarget = 0; vTarget = 0;
@ -198,7 +177,6 @@ public class SuperByteBuffer {
public SuperByteBuffer shiftUVtoSheet(SpriteShiftEntry entry, float uTarget, float vTarget, int sheetSize) { public SuperByteBuffer shiftUVtoSheet(SpriteShiftEntry entry, float uTarget, float vTarget, int sheetSize) {
shouldShiftUV = true; shouldShiftUV = true;
resetUV = false;
spriteShift = entry; spriteShift = entry;
this.uTarget = uTarget; this.uTarget = uTarget;
this.vTarget = vTarget; this.vTarget = vTarget;
@ -206,12 +184,6 @@ public class SuperByteBuffer {
return this; return this;
} }
public SuperByteBuffer dontShiftUV() {
shouldShiftUV = false;
resetUV = true;
return this;
}
public SuperByteBuffer light(int packedLightCoords) { public SuperByteBuffer light(int packedLightCoords) {
shouldLight = true; shouldLight = true;
lightTransform = null; lightTransform = null;
@ -235,11 +207,11 @@ public class SuperByteBuffer {
} }
protected int vertexCount(ByteBuffer buffer) { protected int vertexCount(ByteBuffer buffer) {
return buffer.limit() / FORMAT_LENGTH; return buffer.limit() / formatSize;
} }
protected int getBufferPosition(int vertexIndex) { protected int getBufferPosition(int vertexIndex) {
return vertexIndex * FORMAT_LENGTH; return vertexIndex * formatSize;
} }
protected float getX(ByteBuffer buffer, int index) { protected float getX(ByteBuffer buffer, int index) {
@ -294,32 +266,6 @@ public class SuperByteBuffer {
return buffer.get(getBufferPosition(index) + 30); 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) { private static int getLight(World world, Vector4f lightPos) {
BlockPos.Mutable pos = new BlockPos.Mutable(); BlockPos.Mutable pos = new BlockPos.Mutable();
float sky = 0, block = 0; float sky = 0, block = 0;

View file

@ -2,7 +2,6 @@ package com.simibubi.create.foundation.utility;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -110,14 +109,14 @@ public class SuperByteBufferCache {
} }
private SuperByteBuffer standardModelRender(IBakedModel model, BlockState referenceState, MatrixStack ms) { private SuperByteBuffer standardModelRender(IBakedModel model, BlockState referenceState, MatrixStack ms) {
BlockRendererDispatcher dispatcher = Minecraft.getInstance() Minecraft mc = Minecraft.getInstance();
.getBlockRendererDispatcher(); BlockRendererDispatcher dispatcher = mc.getBlockRendererDispatcher();
BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer();
BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize()); BufferBuilder builder = new BufferBuilder(512);
Random random = new Random();
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
blockRenderer.renderModelFlat(Minecraft.getInstance().world, model, referenceState, BlockPos.ZERO.up(255), ms, blockRenderer.renderModel(mc.world, model, referenceState, BlockPos.ZERO.up(255), ms, builder, true,
builder, true, random, 42, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE); mc.world.rand, 42, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE);
builder.finishDrawing(); builder.finishDrawing();
return new SuperByteBuffer(builder); return new SuperByteBuffer(builder);