Initial experimental rendering changes

This commit is contained in:
tterrag 2020-03-22 15:19:01 -04:00
parent 96106f2a9e
commit c44908b210
6 changed files with 78 additions and 107 deletions

View file

@ -1,31 +1,27 @@
package com.simibubi.create.foundation.block; package com.simibubi.create.foundation.block;
import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
public abstract class SafeTileEntityRenderer<T extends TileEntity> extends TileEntityRenderer<T> { public abstract class SafeTileEntityRenderer<T extends TileEntity> extends TileEntityRenderer<T> {
@Override public SafeTileEntityRenderer(TileEntityRendererDispatcher dispatcher) {
public final void render(T te, double x, double y, double z, float partialTicks, int destroyStage) { super(dispatcher);
if (isInvalid(te))
return;
renderWithGL(te, x, y, z, partialTicks, destroyStage);
} }
protected abstract void renderWithGL(T tileEntityIn, double x, double y, double z, float partialTicks, int destroyStage);
@Override @Override
public final void renderTileEntityFast(T te, double x, double y, double z, float partialTicks, int destroyStage, public void render(T te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) {
BufferBuilder buffer) {
if (isInvalid(te)) if (isInvalid(te))
return; return;
renderFast(te, x, y, z, partialTicks, destroyStage, buffer); renderSafe(te, partialTicks, ms, buffer, light, overlay);
} }
protected void renderFast(T tileEntityIn, double x, double y, double z, float partialTicks, int destroyStage, BufferBuilder buffer) { protected abstract void renderSafe(T te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay);
}
public boolean isInvalid(T te) { public boolean isInvalid(T te) {
return te.getBlockState().getBlock() == Blocks.AIR; return te.getBlockState().getBlock() == Blocks.AIR;

View file

@ -1,25 +0,0 @@
package com.simibubi.create.foundation.block;
import net.minecraft.block.Blocks;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.client.model.animation.TileEntityRendererFast;
public abstract class SafeTileEntityRendererFast<T extends TileEntity> extends TileEntityRendererFast<T> {
@Override
public final void renderTileEntityFast(T te, double x, double y, double z, float partialTicks, int destroyStage,
BufferBuilder buffer) {
if (isInvalid(te))
return;
renderFast(te, x, y, z, partialTicks, destroyStage, buffer);
}
protected abstract void renderFast(T te, double x, double y, double z, float partialTicks, int destroyStage,
BufferBuilder buffer);
public boolean isInvalid(T te) {
return te.getBlockState().getBlock() == Blocks.AIR;
}
}

View file

@ -2,13 +2,17 @@ package com.simibubi.create.foundation.utility;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import javax.vecmath.Matrix4f; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GLAllocation; 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.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
public class SuperByteBuffer { public class SuperByteBuffer {
@ -21,8 +25,7 @@ public class SuperByteBuffer {
protected ByteBuffer mutable; protected ByteBuffer mutable;
// Vertex Position // Vertex Position
private Matrix4f transforms; private MatrixStack transforms;
private Matrix4f t;
// Vertex Texture Coords // Vertex Texture Coords
private boolean shouldShiftUV; private boolean shouldShiftUV;
@ -38,7 +41,8 @@ public class SuperByteBuffer {
private boolean shouldColor; private boolean shouldColor;
private int r, g, b, a; private int r, g, b, a;
public SuperByteBuffer(ByteBuffer original) { public SuperByteBuffer(BufferBuilder buf) {
ByteBuffer original = ObfuscationReflectionHelper.getPrivateValue(BufferBuilder.class, buf, "field_179001_a"); // FIXME speedup
original.rewind(); original.rewind();
this.original = original; this.original = original;
@ -48,28 +52,20 @@ public class SuperByteBuffer {
mutable.put(this.original); mutable.put(this.original);
mutable.rewind(); mutable.rewind();
t = new Matrix4f(); transforms = new MatrixStack();
transforms = new Matrix4f();
transforms.setIdentity();
} }
public ByteBuffer build() { public ByteBuffer build(MatrixStack input) {
original.rewind(); original.rewind();
mutable.rewind(); mutable.rewind();
float x, y, z = 0;
float x2, y2, z2 = 0;
Matrix4f t = transforms; Matrix4f t = transforms.peek().getModel();
t.multiply(input.peek().getModel());
for (int vertex = 0; vertex < vertexCount(original); vertex++) { for (int vertex = 0; vertex < vertexCount(original); vertex++) {
x = getX(original, vertex); Vector4f pos = new Vector4f(getX(original, vertex), getY(original, vertex), getZ(original, vertex), 1F);
y = getY(original, vertex);
z = getZ(original, vertex);
x2 = t.m00 * x + t.m01 * y + t.m02 * z + t.m03; pos.transform(t);
y2 = t.m10 * x + t.m11 * y + t.m12 * z + t.m13; putPos(mutable, vertex, pos.getX(), pos.getY(), pos.getZ());
z2 = t.m20 * x + t.m21 * y + t.m22 * z + t.m23;
putPos(mutable, vertex, x2, y2, z2);
if (shouldColor) { if (shouldColor) {
byte lumByte = getR(original, vertex); byte lumByte = getR(original, vertex);
@ -86,23 +82,26 @@ public class SuperByteBuffer {
if (shouldLight) { if (shouldLight) {
if (vertexLighter != null) if (vertexLighter != null)
putLight(mutable, vertex, putLight(mutable, vertex,
vertexLighter.getPackedLight(x2 + lightOffsetX, y2 + lightOffsetY, z2 + lightOffsetZ)); vertexLighter.getPackedLight(pos.getX() + lightOffsetX, pos.getY() + lightOffsetY, pos.getZ() + lightOffsetZ));
else else
putLight(mutable, vertex, packedLightCoords); putLight(mutable, vertex, packedLightCoords);
} }
} }
t.setIdentity(); transforms = new MatrixStack();
shouldShiftUV = false; shouldShiftUV = false;
shouldColor = false; shouldColor = false;
shouldLight = false; shouldLight = false;
return mutable; return mutable;
} }
public void renderInto(BufferBuilder buffer) { public void renderInto(MatrixStack input, IVertexBuilder buffer) {
if (original.limit() == 0) if (original.limit() == 0)
return; return;
buffer.putBulkData(build()); if (!(buffer instanceof BufferBuilder)) {
throw new IllegalArgumentException("Unsupported buffer type!");
}
((BufferBuilder)buffer).putBulkData(build(input));
} }
public SuperByteBuffer translate(double x, double y, double z) { public SuperByteBuffer translate(double x, double y, double z) {
@ -110,27 +109,18 @@ public class SuperByteBuffer {
} }
public SuperByteBuffer translate(float x, float y, float z) { public SuperByteBuffer translate(float x, float y, float z) {
transforms.m03 += x; transforms.translate(x, y, z);
transforms.m13 += y;
transforms.m23 += z;
return this; return this;
} }
public SuperByteBuffer rotate(Axis axis, float angle) { public SuperByteBuffer rotate(Direction axis, float angle) {
if (angle == 0) if (angle == 0)
return this; return this;
t.setIdentity(); transforms.multiply(axis.getUnitVector().getDegreesQuaternion(angle));
if (axis == Axis.X)
t.rotX(angle);
else if (axis == Axis.Y)
t.rotY(angle);
else
t.rotZ(angle);
transforms.mul(t, transforms);
return this; return this;
} }
public SuperByteBuffer rotateCentered(Axis axis, float angle) { public SuperByteBuffer rotateCentered(Direction axis, float angle) {
return translate(-.5f, -.5f, -.5f).rotate(axis, angle).translate(.5f, .5f, .5f); return translate(-.5f, -.5f, -.5f).rotate(axis, angle).translate(.5f, .5f, .5f);
} }

View file

@ -11,6 +11,7 @@ import org.lwjgl.opengl.GL11;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlockPartials;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -19,6 +20,7 @@ import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.BlockRendererDispatcher; import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraftforge.client.model.data.EmptyModelData; import net.minecraftforge.client.model.data.EmptyModelData;
@ -84,14 +86,16 @@ public class SuperByteBufferCache {
BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer();
BufferBuilder builder = new BufferBuilder(0); BufferBuilder builder = new BufferBuilder(0);
Random random = new Random(); Random random = new Random();
MatrixStack ms = new MatrixStack();
ms.push();
ms.translate(0, 1, 0);
builder.setTranslation(0, 1, 0);
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
blockRenderer.renderModelFlat(Minecraft.getInstance().world, model, referenceState, BlockPos.ZERO.down(), blockRenderer.renderModelFlat(Minecraft.getInstance().world, model, referenceState, BlockPos.ZERO.down(), ms,
builder, true, random, 42, EmptyModelData.INSTANCE); builder, true, random, 42, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE);
builder.finishDrawing(); builder.finishDrawing();
return new SuperByteBuffer(builder.getByteBuffer()); return new SuperByteBuffer(builder);
} }
public void invalidate() { public void invalidate() {

View file

@ -1,8 +1,10 @@
package com.simibubi.create.modules.contraptions.base; package com.simibubi.create.modules.contraptions.base;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient; import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.block.SafeTileEntityRendererFast; import com.simibubi.create.foundation.block.SafeTileEntityRenderer;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.SuperByteBuffer; import com.simibubi.create.foundation.utility.SuperByteBuffer;
@ -11,33 +13,39 @@ import com.simibubi.create.modules.contraptions.KineticDebugger;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(value = Dist.CLIENT) @EventBusSubscriber(value = Dist.CLIENT)
public class KineticTileEntityRenderer extends SafeTileEntityRendererFast<KineticTileEntity> { public class KineticTileEntityRenderer extends SafeTileEntityRenderer<KineticTileEntity> {
public static final Compartment<BlockState> KINETIC_TILE = new Compartment<>(); public static final Compartment<BlockState> KINETIC_TILE = new Compartment<>();
public static boolean rainbowMode = false; public static boolean rainbowMode = false;
public KineticTileEntityRenderer(TileEntityRendererDispatcher dispatcher) {
super(dispatcher);
}
@Override @Override
public void renderFast(KineticTileEntity te, double x, double y, double z, float partialTicks, int destroyStage, protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
BufferBuilder buffer) { int light, int overlay) {
renderRotatingBuffer(te, getWorld(), getRotatedModel(te), x, y, z, buffer); renderRotatingBuffer(te, getRotatedModel(te), ms, buffer.getBuffer(RenderType.getSolid()));
} }
public static void renderRotatingKineticBlock(KineticTileEntity te, World world, BlockState renderedState, double x, public static void renderRotatingKineticBlock(KineticTileEntity te, BlockState renderedState, MatrixStack ms, BufferBuilder buffer) {
double y, double z, BufferBuilder buffer) {
SuperByteBuffer superByteBuffer = CreateClient.bufferCache.renderBlockIn(KINETIC_TILE, renderedState); SuperByteBuffer superByteBuffer = CreateClient.bufferCache.renderBlockIn(KINETIC_TILE, renderedState);
renderRotatingBuffer(te, world, superByteBuffer, x, y, z, buffer); renderRotatingBuffer(te, superByteBuffer, ms, buffer);
} }
public static void renderRotatingBuffer(KineticTileEntity te, World world, SuperByteBuffer superBuffer, double x, public static void renderRotatingBuffer(KineticTileEntity te, SuperByteBuffer superBuffer, MatrixStack ms, IVertexBuilder buffer) {
double y, double z, BufferBuilder buffer) { standardKineticRotationTransform(superBuffer, te).renderInto(ms, buffer);
buffer.putBulkData(standardKineticRotationTransform(superBuffer, te, world).translate(x, y, z).build());
} }
public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) { public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) {
@ -47,18 +55,17 @@ public class KineticTileEntityRenderer extends SafeTileEntityRendererFast<Kineti
return angle; return angle;
} }
public static SuperByteBuffer standardKineticRotationTransform(SuperByteBuffer buffer, KineticTileEntity te, public static SuperByteBuffer standardKineticRotationTransform(SuperByteBuffer buffer, KineticTileEntity te) {
World world) {
final BlockPos pos = te.getPos(); final BlockPos pos = te.getPos();
Axis axis = ((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState()); Axis axis = ((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState());
return kineticRotationTransform(buffer, te, axis, getAngleForTe(te, pos, axis), world); return kineticRotationTransform(buffer, te, axis, getAngleForTe(te, pos, axis));
} }
public static SuperByteBuffer kineticRotationTransform(SuperByteBuffer buffer, KineticTileEntity te, Axis axis, public static SuperByteBuffer kineticRotationTransform(SuperByteBuffer buffer, KineticTileEntity te, Axis axis,
float angle, World world) { float angle) {
int packedLightmapCoords = te.getBlockState().getPackedLightmapCoords(world, te.getPos()); int light = te.getBlockState().getLightValue(te.getWorld(), te.getPos());
buffer.light(packedLightmapCoords); buffer.light((0xF0 << 24) | (light << 4));
buffer.rotateCentered(axis, angle); buffer.rotateCentered(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis), angle);
int white = 0xFFFFFF; int white = 0xFFFFFF;
if (KineticDebugger.isActive()) { if (KineticDebugger.isActive()) {

View file

@ -111,7 +111,6 @@ public class ContraptionRenderer {
Random random = new Random(); Random random = new Random();
BufferBuilder builder = new BufferBuilder(0); BufferBuilder builder = new BufferBuilder(0);
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
builder.setTranslation(0, 0, 0);
for (BlockInfo info : c.blocks.values()) for (BlockInfo info : c.blocks.values())
renderWorld.setBlockState(info.pos, info.state); renderWorld.setBlockState(info.pos, info.state);
@ -129,7 +128,7 @@ public class ContraptionRenderer {
builder.finishDrawing(); builder.finishDrawing();
renderWorld.clear(); renderWorld.clear();
return new SuperByteBuffer(builder.getByteBuffer()); return new SuperByteBuffer(builder);
} }
private static void renderActors(World world, Contraption c, Consumer<SuperByteBuffer> transform, private static void renderActors(World world, Contraption c, Consumer<SuperByteBuffer> transform,
@ -158,7 +157,7 @@ public class ContraptionRenderer {
} }
public static int getLight(World world, float lx, float ly, float lz) { public static int getLight(World world, float lx, float ly, float lz) {
MutableBlockPos pos = new MutableBlockPos(); BlockPos.Mutable pos = new BlockPos.Mutable();
float sky = 0, block = 0; float sky = 0, block = 0;
float offset = 1 / 8f; float offset = 1 / 8f;
@ -166,8 +165,8 @@ public class ContraptionRenderer {
for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset) for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset)
for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) { for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) {
pos.setPos(lx + xOffset, ly + yOffset, lz + zOffset); pos.setPos(lx + xOffset, ly + yOffset, lz + zOffset);
sky += world.getLightFor(LightType.SKY, pos) / 8f; sky += world.getLightLevel(LightType.SKY, pos) / 8f;
block += world.getLightFor(LightType.BLOCK, pos) / 8f; block += world.getLightLevel(LightType.BLOCK, pos) / 8f;
} }
return ((int) sky) << 20 | ((int) block) << 4; return ((int) sky) << 20 | ((int) block) << 4;