) materials.computeIfAbsent(spec, this::createInstanceMaterial);
- }
-
- private InstanceMaterial> createInstanceMaterial(MaterialSpec> type) {
- InstanceMaterial> material = new InstanceMaterial<>(owner::getOriginCoordinate, type);
-
- this.renderers.add(new MaterialRenderer<>(owner.getProgram(type.getProgramName()), material, this::setup));
-
- return material;
- }
-
public void clear() {
materials.values().forEach(InstanceMaterial::clear);
}
@@ -58,4 +62,12 @@ public class MaterialGroup {
materials.clear();
renderers.clear();
}
+
+ private InstanceMaterial> createInstanceMaterial(MaterialSpec> type) {
+ InstanceMaterial> material = new InstanceMaterial<>(type);
+
+ this.renderers.add(new MaterialRenderer<>(owner.getProgram(type.getProgramName()), material, this::setup));
+
+ return material;
+ }
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialManager.java b/src/main/java/com/jozufozu/flywheel/backend/material/MaterialManager.java
index d9436c117..869be4cff 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialManager.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/material/MaterialManager.java
@@ -60,9 +60,44 @@ public class MaterialManager
{
}
}
+ /**
+ * Get a material group that will render in the given layer with the given state.
+ *
+ * @param layer The {@link RenderLayer} you want to draw in.
+ * @param state The {@link IRenderState} you need to draw with.
+ * @return A material group whose children will
+ */
+ public MaterialGroup
state(RenderLayer layer, IRenderState state) {
+ return layers.get(layer).computeIfAbsent(state, this::createGroup);
+ }
+
+ public MaterialGroup
solid(IRenderState state) {
+ return layers.get(RenderLayer.SOLID).computeIfAbsent(state, this::createGroup);
+ }
+
+ public MaterialGroup
cutout(IRenderState state) {
+ return layers.get(RenderLayer.CUTOUT).computeIfAbsent(state, this::createGroup);
+ }
+
+ public MaterialGroup
transparent(IRenderState state) {
+ return layers.get(RenderLayer.TRANSPARENT).computeIfAbsent(state, this::createGroup);
+ }
+
+ public MaterialGroup
defaultSolid() {
+ return solid(TextureRenderState.get(PlayerContainer.BLOCK_ATLAS));
+ }
+
+ public MaterialGroup
defaultCutout() {
+ return cutout(TextureRenderState.get(PlayerContainer.BLOCK_ATLAS));
+ }
+
+ public MaterialGroup
defaultTransparent() {
+ return transparent(TextureRenderState.get(PlayerContainer.BLOCK_ATLAS));
+ }
+
/**
* Render every model for every material.
- * @param layer Which vanilla {@link RenderType} is being drawn?
+ * @param layer Which of the 3 {@link RenderLayer render layers} is being drawn?
* @param viewProjection How do we get from camera space to clip space?
*/
public void render(RenderLayer layer, Matrix4f viewProjection, double camX, double camY, double camZ) {
@@ -95,34 +130,6 @@ public class MaterialManager
{
}
}
- public MaterialGroup
state(RenderLayer layer, IRenderState state) {
- return layers.get(layer).computeIfAbsent(state, this::createGroup);
- }
-
- public MaterialGroup
solid(IRenderState state) {
- return layers.get(RenderLayer.SOLID).computeIfAbsent(state, this::createGroup);
- }
-
- public MaterialGroup
cutout(IRenderState state) {
- return layers.get(RenderLayer.CUTOUT).computeIfAbsent(state, this::createGroup);
- }
-
- public MaterialGroup
transparent(IRenderState state) {
- return layers.get(RenderLayer.TRANSPARENT).computeIfAbsent(state, this::createGroup);
- }
-
- public MaterialGroup
defaultSolid() {
- return solid(TextureRenderState.get(PlayerContainer.BLOCK_ATLAS));
- }
-
- public MaterialGroup
defaultCutout() {
- return cutout(TextureRenderState.get(PlayerContainer.BLOCK_ATLAS));
- }
-
- public MaterialGroup
defaultTransparent() {
- return transparent(TextureRenderState.get(PlayerContainer.BLOCK_ATLAS));
- }
-
@Deprecated
public InstanceMaterial getMaterial(MaterialSpec materialType) {
return defaultCutout().material(materialType);
@@ -155,6 +162,11 @@ public class MaterialManager {
listeners.add(listener);
}
+ /**
+ * Maintain the integer origin coordinate to be within a certain distance from the camera in all directions.
+ *
+ * This prevents floating point precision issues at high coordinates.
+ */
public void checkAndShiftOrigin(ActiveRenderInfo info) {
int cX = MathHelper.floor(info.getPosition().x);
int cY = MathHelper.floor(info.getPosition().y);
diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialSpec.java b/src/main/java/com/jozufozu/flywheel/backend/material/MaterialSpec.java
index 8946fcbff..9b3a87b5a 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialSpec.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/material/MaterialSpec.java
@@ -4,7 +4,6 @@ import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.instancing.IInstanceFactory;
import com.jozufozu.flywheel.backend.instancing.InstanceData;
-import net.minecraft.inventory.container.PlayerContainer;
import net.minecraft.util.ResourceLocation;
public class MaterialSpec {
@@ -15,19 +14,13 @@ public class MaterialSpec {
private final VertexFormat modelFormat;
private final VertexFormat instanceFormat;
private final IInstanceFactory instanceFactory;
- private final ResourceLocation texture;
public MaterialSpec(ResourceLocation name, ResourceLocation programSpec, VertexFormat modelFormat, VertexFormat instanceFormat, IInstanceFactory instanceFactory) {
- this(name, programSpec, modelFormat, instanceFormat, PlayerContainer.BLOCK_ATLAS, instanceFactory);
- }
-
- public MaterialSpec(ResourceLocation name, ResourceLocation programSpec, VertexFormat modelFormat, VertexFormat instanceFormat, ResourceLocation texture, IInstanceFactory instanceFactory) {
this.name = name;
this.programSpec = programSpec;
this.modelFormat = modelFormat;
this.instanceFormat = instanceFormat;
this.instanceFactory = instanceFactory;
- this.texture = texture;
}
public ResourceLocation getProgramName() {
diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/package-info.java b/src/main/java/com/jozufozu/flywheel/backend/material/package-info.java
new file mode 100644
index 000000000..da6906de5
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/backend/material/package-info.java
@@ -0,0 +1,6 @@
+@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
+package com.jozufozu.flywheel.backend.material;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
+import mcp.MethodsReturnNonnullByDefault;
diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/ArrayModelRenderer.java b/src/main/java/com/jozufozu/flywheel/backend/model/ArrayModelRenderer.java
index 5347e74d1..48359821c 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/model/ArrayModelRenderer.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/model/ArrayModelRenderer.java
@@ -1,23 +1,23 @@
package com.jozufozu.flywheel.backend.model;
+import java.util.function.Supplier;
+
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
+import com.jozufozu.flywheel.core.model.IModel;
+import com.jozufozu.flywheel.util.AttribUtil;
public class ArrayModelRenderer extends ModelRenderer {
protected GlVertexArray vao;
- public ArrayModelRenderer(BufferedModel model) {
+ public ArrayModelRenderer(Supplier model) {
super(model);
- vao = new GlVertexArray();
-
- vao.bind();
- model.setupState();
- vao.unbind();
- model.clearState();
}
+ @Override
public void draw() {
- if (!model.valid()) return;
+ if (!initialized) init();
+ if (!isValid()) return;
vao.bind();
@@ -25,4 +25,27 @@ public class ArrayModelRenderer extends ModelRenderer {
vao.unbind();
}
+
+ @Override
+ protected void init() {
+ initialized = true;
+ IModel model = modelSupplier.get();
+
+ if (model.empty()) return;
+
+ this.model = new IndexedModel(model);
+
+ vao = new GlVertexArray();
+
+ vao.bind();
+
+ // bind the model's vbo to our vao
+ this.model.setupState();
+
+ AttribUtil.enableArrays(this.model.getAttributeCount());
+
+ vao.unbind();
+
+ this.model.clearState();
+ }
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/BufferedModel.java b/src/main/java/com/jozufozu/flywheel/backend/model/BufferedModel.java
index 3c775cfbb..5808c177e 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/model/BufferedModel.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/model/BufferedModel.java
@@ -9,46 +9,45 @@ import com.jozufozu.flywheel.backend.gl.GlPrimitive;
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.jozufozu.flywheel.core.model.IModel;
import com.jozufozu.flywheel.util.AttribUtil;
-public class BufferedModel {
+public class BufferedModel implements IBufferedModel {
+ protected final IModel model;
protected final GlPrimitive primitiveMode;
- protected final ByteBuffer data;
- protected final VertexFormat format;
- protected final int vertexCount;
protected GlBuffer vbo;
protected boolean deleted;
- public BufferedModel(GlPrimitive primitiveMode, VertexFormat format, ByteBuffer data, int vertices) {
+ public BufferedModel(GlPrimitive primitiveMode, IModel model) {
+ this.model = model;
this.primitiveMode = primitiveMode;
- this.data = data;
- this.format = format;
- this.vertexCount = vertices;
vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER);
vbo.bind();
// allocate the buffer on the gpu
- vbo.alloc(this.data.capacity());
+ vbo.alloc(model.size());
// mirror it in system memory so we can write to it, and upload our model.
- vbo.getBuffer(0, this.data.capacity())
- .put(this.data)
- .flush();
+ MappedBuffer buffer = vbo.getBuffer(0, model.size());
+ model.buffer(buffer);
+ buffer.flush();
+
vbo.unbind();
}
public VertexFormat getFormat() {
- return format;
+ return model.format();
}
public int getVertexCount() {
- return vertexCount;
+ return model.vertexCount();
}
public boolean valid() {
- return vertexCount > 0 && !deleted;
+ return getVertexCount() > 0 && !deleted;
}
/**
@@ -57,7 +56,7 @@ public class BufferedModel {
public void setupState() {
vbo.bind();
AttribUtil.enableArrays(getAttributeCount());
- format.vertexAttribPointers(0);
+ getFormat().vertexAttribPointers(0);
}
public void clearState() {
@@ -66,7 +65,7 @@ public class BufferedModel {
}
public void drawCall() {
- glDrawArrays(primitiveMode.glEnum, 0, vertexCount);
+ glDrawArrays(primitiveMode.glEnum, 0, getVertexCount());
}
/**
@@ -75,7 +74,7 @@ public class BufferedModel {
public void drawInstances(int instanceCount) {
if (!valid()) return;
- Backend.getInstance().compat.drawInstanced.drawArraysInstanced(primitiveMode, 0, vertexCount, instanceCount);
+ Backend.getInstance().compat.drawInstanced.drawArraysInstanced(primitiveMode, 0, getVertexCount(), instanceCount);
}
public void delete() {
@@ -84,10 +83,5 @@ public class BufferedModel {
deleted = true;
vbo.delete();
}
-
- public int getAttributeCount() {
- return format.getAttributeCount();
- }
-
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/IBufferedModel.java b/src/main/java/com/jozufozu/flywheel/backend/model/IBufferedModel.java
new file mode 100644
index 000000000..4ac73c572
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/backend/model/IBufferedModel.java
@@ -0,0 +1,32 @@
+package com.jozufozu.flywheel.backend.model;
+
+import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
+
+public interface IBufferedModel {
+
+ VertexFormat getFormat();
+
+ int getVertexCount();
+
+ boolean valid();
+
+ /**
+ * The VBO/VAO should be bound externally.
+ */
+ void setupState();
+
+ void clearState();
+
+ void drawCall();
+
+ /**
+ * Draws many instances of this model, assuming the appropriate state is already bound.
+ */
+ void drawInstances(int instanceCount);
+
+ void delete();
+
+ default int getAttributeCount() {
+ return getFormat().getAttributeCount();
+ }
+}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java b/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java
index 628491766..9ae5c8c47 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java
@@ -8,6 +8,7 @@ import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.core.QuadConverter;
+import com.jozufozu.flywheel.core.model.IModel;
/**
* An indexed triangle model. Just what the driver ordered.
@@ -18,15 +19,10 @@ public class IndexedModel extends BufferedModel {
protected ElementBuffer ebo;
- public IndexedModel(VertexFormat modelFormat, ByteBuffer buf, int vertices, ElementBuffer ebo) {
- super(GlPrimitive.TRIANGLES, modelFormat, buf, vertices);
+ public IndexedModel(IModel model) {
+ super(GlPrimitive.TRIANGLES, model);
- this.ebo = ebo;
- }
-
- public static IndexedModel fromSequentialQuads(VertexFormat modelFormat, ByteBuffer quads, int vertices) {
- return new IndexedModel(modelFormat, quads, vertices, QuadConverter.getInstance()
- .quads2Tris(vertices / 4));
+ this.ebo = model.createEBO();
}
@Override
@@ -48,13 +44,8 @@ public class IndexedModel extends BufferedModel {
@Override
public void drawInstances(int instanceCount) {
- if (vertexCount <= 0 || deleted) return;
+ if (!valid()) return;
Backend.getInstance().compat.drawInstanced.drawElementsInstanced(primitiveMode, ebo.elementCount, ebo.eboIndexType, 0, instanceCount);
}
-
- @Override
- public void delete() {
- super.delete();
- }
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/ModelRenderer.java b/src/main/java/com/jozufozu/flywheel/backend/model/ModelRenderer.java
index fd1efd896..72a11d601 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/model/ModelRenderer.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/model/ModelRenderer.java
@@ -1,18 +1,26 @@
package com.jozufozu.flywheel.backend.model;
+import java.util.function.Supplier;
+
+import com.jozufozu.flywheel.core.model.IModel;
+
public class ModelRenderer {
- protected BufferedModel model;
+ protected Supplier modelSupplier;
+ protected IBufferedModel model;
- public ModelRenderer(BufferedModel model) {
- this.model = model;
+ protected boolean initialized;
+
+ public ModelRenderer(Supplier modelSupplier) {
+ this.modelSupplier = modelSupplier;
}
/**
* Renders this model, checking first if there is anything to render.
*/
public void draw() {
- if (!model.valid()) return;
+ if (!initialized) init();
+ if (!isValid()) return;
model.setupState();
model.drawCall();
@@ -20,6 +28,20 @@ public class ModelRenderer {
}
public void delete() {
- model.delete();
+ if (model != null)
+ model.delete();
+ }
+
+ protected void init() {
+ initialized = true;
+ IModel model = modelSupplier.get();
+
+ if (model.empty()) return;
+
+ this.model = new IndexedModel(model);
+ }
+
+ protected boolean isValid() {
+ return model != null && model.valid();
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/state/RenderLayer.java b/src/main/java/com/jozufozu/flywheel/backend/state/RenderLayer.java
index 231e5cead..8594f1f00 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/state/RenderLayer.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/state/RenderLayer.java
@@ -4,9 +4,36 @@ import javax.annotation.Nullable;
import net.minecraft.client.renderer.RenderType;
+/**
+ * The 3 discrete stages the world is rendered in.
+ */
public enum RenderLayer {
+ /**
+ * Solid layer:
+ *
+ * All polygons will entirely occlude everything behind them.
+ *
+ *
+ * e.g. stone, dirt, solid blocks
+ */
SOLID,
+ /**
+ * Cutout layer:
+ *
+ * Fragments will either occlude or not occlude depending on the texture/material.
+ *
+ *
+ * e.g. leaves, cobwebs, tall grass, saplings, glass
+ */
CUTOUT,
+ /**
+ * Transparent layer:
+ *
+ * Nothing is guaranteed to occlude and fragments blend their color with what's behind them.
+ *
+ *
+ * e.g. stained glass, water
+ */
TRANSPARENT,
;
diff --git a/src/main/java/com/jozufozu/flywheel/backend/state/package-info.java b/src/main/java/com/jozufozu/flywheel/backend/state/package-info.java
new file mode 100644
index 000000000..0fb20311b
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/backend/state/package-info.java
@@ -0,0 +1,6 @@
+@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
+package com.jozufozu.flywheel.backend.state;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
+import mcp.MethodsReturnNonnullByDefault;
diff --git a/src/main/java/com/jozufozu/flywheel/config/BooleanConfig.java b/src/main/java/com/jozufozu/flywheel/config/BooleanConfig.java
index 8d143dea9..98f8701f2 100644
--- a/src/main/java/com/jozufozu/flywheel/config/BooleanConfig.java
+++ b/src/main/java/com/jozufozu/flywheel/config/BooleanConfig.java
@@ -18,6 +18,7 @@ import net.minecraftforge.api.distmarker.OnlyIn;
public enum BooleanConfig {
ENGINE(() -> BooleanConfig::enabled),
NORMAL_OVERLAY(() -> BooleanConfig::normalOverlay),
+ CHUNK_CACHING(() -> BooleanConfig::chunkCaching),
;
final Supplier> receiver;
@@ -71,6 +72,25 @@ public enum BooleanConfig {
player.displayClientMessage(text, false);
}
+ @OnlyIn(Dist.CLIENT)
+ private static void chunkCaching(BooleanDirective state) {
+ ClientPlayerEntity player = Minecraft.getInstance().player;
+ if (player == null || state == null) return;
+
+ if (state == BooleanDirective.DISPLAY) {
+ ITextComponent text = new StringTextComponent("Chunk caching is currently: ").append(boolToText(FlwConfig.get().client.chunkCaching.get()));
+ player.displayClientMessage(text, false);
+ return;
+ }
+
+ FlwConfig.get().client.chunkCaching.set(state.get());
+
+ ITextComponent text = boolToText(FlwConfig.get().client.chunkCaching.get()).append(new StringTextComponent(" chunk caching").withStyle(TextFormatting.WHITE));
+
+ player.displayClientMessage(text, false);
+ Backend.reloadWorldRenderers();
+ }
+
private static IFormattableTextComponent boolToText(boolean b) {
return b ? new StringTextComponent("enabled").withStyle(TextFormatting.DARK_GREEN) : new StringTextComponent("disabled").withStyle(TextFormatting.RED);
}
diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java b/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java
index fe58438d0..a601971cb 100644
--- a/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java
+++ b/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java
@@ -16,6 +16,8 @@ public class FlwCommands {
dispatcher.register(Commands.literal("flywheel")
.then(new BooleanConfigCommand("backend", BooleanConfig.ENGINE).register())
- .then(new BooleanConfigCommand("debugNormals", BooleanConfig.NORMAL_OVERLAY).register()));
+ .then(new BooleanConfigCommand("debugNormals", BooleanConfig.NORMAL_OVERLAY).register())
+ .then(new BooleanConfigCommand("chunkCaching", BooleanConfig.CHUNK_CACHING).register())
+ );
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java
index 0fd5a2673..359d7111e 100644
--- a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java
+++ b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java
@@ -34,12 +34,17 @@ public class FlwConfig {
return client.debugNormals.get();
}
+ public boolean chunkCaching() {
+ return client.chunkCaching.get();
+ }
+
public static void init() {
}
public static class ClientConfig {
public final BooleanValue enabled;
public final BooleanValue debugNormals;
+ public final BooleanValue chunkCaching;
public ClientConfig(ForgeConfigSpec.Builder builder) {
@@ -48,6 +53,9 @@ public class FlwConfig {
debugNormals = builder.comment("Enable or disable a debug overlay that colors pixels by their normal")
.define("debugNormals", false);
+
+ chunkCaching = builder.comment("Cache chunk lookups to improve performance.")
+ .define("chunkCaching", true);
}
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/core/Clipping.java b/src/main/java/com/jozufozu/flywheel/core/Clipping.java
new file mode 100644
index 000000000..9f28ef46e
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/core/Clipping.java
@@ -0,0 +1,16 @@
+package com.jozufozu.flywheel.core;
+
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import net.minecraft.client.renderer.culling.ClippingHelper;
+
+/**
+ * Used to capture the ClippingHelper from WorldRenderer#renderLevel
+ */
+public class Clipping {
+
+ /**
+ * Assigned in {@link com.jozufozu.flywheel.mixin.GlobalClippingHelperMixin this} mixin.
+ */
+ public static ClippingHelper HELPER;
+}
diff --git a/src/main/java/com/jozufozu/flywheel/core/Formats.java b/src/main/java/com/jozufozu/flywheel/core/Formats.java
index e7cca829a..6632c2117 100644
--- a/src/main/java/com/jozufozu/flywheel/core/Formats.java
+++ b/src/main/java/com/jozufozu/flywheel/core/Formats.java
@@ -9,12 +9,21 @@ public class Formats {
.addAttributes(CommonAttributes.VEC3, CommonAttributes.NORMAL, CommonAttributes.UV)
.build();
+ public static final VertexFormat COLORED_LIT_MODEL = VertexFormat.builder()
+ .addAttributes(CommonAttributes.VEC3,
+ CommonAttributes.NORMAL,
+ CommonAttributes.UV,
+ CommonAttributes.RGBA,
+ CommonAttributes.LIGHT)
+ .build();
+
public static final VertexFormat TRANSFORMED = litInstance().addAttributes(MatrixAttributes.MAT4, MatrixAttributes.MAT3)
.build();
+
public static final VertexFormat ORIENTED = litInstance().addAttributes(CommonAttributes.VEC3, CommonAttributes.VEC3, CommonAttributes.QUATERNION)
.build();
- public static VertexFormat.Builder litInstance() {
+ public static VertexFormat.Builder litInstance() {
return VertexFormat.builder()
.addAttributes(CommonAttributes.LIGHT, CommonAttributes.RGBA);
}
diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java
index caca38784..5415512dc 100644
--- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java
+++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java
@@ -53,8 +53,6 @@ public class CrumblingRenderer {
INVALIDATOR = state.getSecond();
}
- private static final RenderType crumblingLayer = ModelBakery.DESTROY_TYPES.get(0);
-
public static void renderBreaking(ClientWorld world, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) {
if (!Backend.getInstance()
.canUseInstancing(world)) return;
@@ -64,6 +62,7 @@ public class CrumblingRenderer {
if (activeStages.isEmpty()) return;
State state = STATE.get();
+ RenderType layer = ModelBakery.DESTROY_TYPES.get(0);
InstanceManager renderer = state.instanceManager;
@@ -71,7 +70,7 @@ public class CrumblingRenderer {
ActiveRenderInfo info = Minecraft.getInstance().gameRenderer.getMainCamera();
MaterialManager materials = state.materialManager;
- crumblingLayer.setupRenderState();
+ layer.setupRenderState();
for (Int2ObjectMap.Entry> stage : activeStages.int2ObjectEntrySet()) {
int i = stage.getIntKey();
@@ -92,7 +91,7 @@ public class CrumblingRenderer {
}
- crumblingLayer.clearRenderState();
+ layer.clearRenderState();
GlTextureUnit.T0.makeActive();
Texture breaking = textureManager.getTexture(ModelBakery.BREAKING_LOCATIONS.get(0));
diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/package-info.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/package-info.java
new file mode 100644
index 000000000..00190daac
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/package-info.java
@@ -0,0 +1,6 @@
+@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
+package com.jozufozu.flywheel.core.crumbling;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
+import mcp.MethodsReturnNonnullByDefault;
diff --git a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java
index 3a30847c6..8ddb4aed2 100644
--- a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java
+++ b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java
@@ -23,6 +23,9 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
+/**
+ * A model of a single block.
+ */
public class BlockModel implements IModel {
private static final MatrixStack IDENTITY = new MatrixStack();
@@ -30,6 +33,12 @@ public class BlockModel implements IModel {
private final VertexFormat modelFormat;
+ public BlockModel(VertexFormat modelFormat, BlockState state) {
+ this(modelFormat, Minecraft.getInstance()
+ .getBlockRenderer()
+ .getBlockModel(state), state);
+ }
+
public BlockModel(VertexFormat modelFormat, IBakedModel model, BlockState referenceState) {
this(modelFormat, model, referenceState, IDENTITY);
}
@@ -63,12 +72,6 @@ public class BlockModel implements IModel {
}
}
- @Override
- public ElementBuffer createEBO() {
- return QuadConverter.getInstance()
- .quads2Tris(vertexCount() / 4);
- }
-
public static BufferBuilder getBufferBuilder(IBakedModel model, BlockState referenceState, MatrixStack ms) {
Minecraft mc = Minecraft.getInstance();
BlockRendererDispatcher dispatcher = mc.getBlockRenderer();
diff --git a/src/main/java/com/jozufozu/flywheel/core/model/IModel.java b/src/main/java/com/jozufozu/flywheel/core/model/IModel.java
index 4c3e9d027..b7ffd1a1b 100644
--- a/src/main/java/com/jozufozu/flywheel/core/model/IModel.java
+++ b/src/main/java/com/jozufozu/flywheel/core/model/IModel.java
@@ -3,9 +3,27 @@ package com.jozufozu.flywheel.core.model;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.backend.model.ElementBuffer;
+import com.jozufozu.flywheel.core.QuadConverter;
/**
* A model that can be rendered by flywheel.
+ *
+ *
+ * It is expected that the following assertion will not fail:
+ *
+ *
+ * {@code
+ * IModel model = ...;
+ * VecBuffer into = ...;
+ *
+ * int initial = VecBuffer.unwrap().position();
+ *
+ * model.buffer(into);
+ *
+ * int final = VecBuffer.unwrap().position();
+ *
+ * assert model.size() == final - initial;
+ * }
*/
public interface IModel {
@@ -14,13 +32,43 @@ public interface IModel {
*/
void buffer(VecBuffer buffer);
+ /**
+ * @return The number of vertices the model has.
+ */
int vertexCount();
+ /**
+ * @return The format of this model's vertices
+ */
VertexFormat format();
- ElementBuffer createEBO();
+ /**
+ * Create an element buffer object that indexes the vertices of this model.
+ *
+ *
+ * Very often models in minecraft are made up of sequential quads, which is a very predictable pattern.
+ * The default implementation accommodates this, however this can be overridden to change the behavior and
+ * support more complex models.
+ *
+ * @return an element buffer object indexing this model's vertices.
+ */
+ default ElementBuffer createEBO() {
+ return QuadConverter.getInstance()
+ .quads2Tris(vertexCount() / 4);
+ }
+ /**
+ * The size in bytes that this model's data takes up.
+ */
default int size() {
return vertexCount() * format().getStride();
}
+
+ /**
+ * Is there nothing to render?
+ * @return true if there are no vertices.
+ */
+ default boolean empty() {
+ return vertexCount() == 0;
+ }
}
diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java b/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java
index fff356878..6e81c7d2e 100644
--- a/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java
+++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java
@@ -43,10 +43,4 @@ public class ModelPart implements IModel {
public VertexFormat format() {
return Formats.UNLIT_MODEL;
}
-
- @Override
- public ElementBuffer createEBO() {
- return QuadConverter.getInstance()
- .quads2Tris(vertices / 4);
- }
}
diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java
index 3039e2218..52b69403d 100644
--- a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java
+++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java
@@ -1,21 +1,62 @@
package com.jozufozu.flywheel.core.model;
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
+import static org.lwjgl.opengl.GL11.GL_QUADS;
-import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
-import com.jozufozu.flywheel.backend.model.IndexedModel;
+
+import java.util.Collection;
+import java.util.Random;
+
+import com.mojang.blaze3d.matrix.MatrixStack;
+
+import net.minecraft.block.BlockRenderType;
+import net.minecraft.block.BlockState;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.BlockModelRenderer;
+import net.minecraft.client.renderer.BlockModelShapes;
+import net.minecraft.client.renderer.BufferBuilder;
+import net.minecraft.client.renderer.RenderType;
+import net.minecraft.client.renderer.RenderTypeLookup;
+import net.minecraft.client.renderer.texture.OverlayTexture;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.IBlockDisplayReader;
+import net.minecraft.world.gen.feature.template.Template;
+import net.minecraftforge.client.ForgeHooksClient;
+import net.minecraftforge.client.model.data.EmptyModelData;
+import net.minecraftforge.common.util.Lazy;
public class ModelUtil {
- public static IndexedModel getIndexedModel(IModel blockModel) {
- ByteBuffer vertices = ByteBuffer.allocate(blockModel.size());
- vertices.order(ByteOrder.nativeOrder());
+ private static final Lazy MODEL_RENDERER = Lazy.of(() -> new BlockModelRenderer(Minecraft.getInstance().getBlockColors()));
+ private static final Lazy BLOCK_MODELS = Lazy.of(() -> Minecraft.getInstance().getModelManager().getBlockModelShaper());
- blockModel.buffer(new VecBuffer(vertices));
+ public static BufferBuilder getBufferBuilderFromTemplate(IBlockDisplayReader renderWorld, RenderType layer, Collection blocks) {
+ MatrixStack ms = new MatrixStack();
+ Random random = new Random();
+ BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize());
+ builder.begin(GL_QUADS, DefaultVertexFormats.BLOCK);
- ((Buffer) vertices).rewind();
+ ForgeHooksClient.setRenderLayer(layer);
+ BlockModelRenderer.enableCaching();
+ for (Template.BlockInfo info : blocks) {
+ BlockState state = info.state;
- return new IndexedModel(blockModel.format(), vertices, blockModel.vertexCount(), blockModel.createEBO());
+ if (state.getRenderShape() != BlockRenderType.MODEL)
+ continue;
+ if (!RenderTypeLookup.canRenderInLayer(state, layer))
+ continue;
+
+ BlockPos pos = info.pos;
+
+ ms.pushPose();
+ ms.translate(pos.getX(), pos.getY(), pos.getZ());
+ MODEL_RENDERER.get().renderModel(renderWorld, BLOCK_MODELS.get().getBlockModel(state), state, pos, ms, builder, true,
+ random, 42, OverlayTexture.NO_OVERLAY, EmptyModelData.INSTANCE);
+ ms.popPose();
+ }
+ BlockModelRenderer.clearCache();
+ ForgeHooksClient.setRenderLayer(null);
+
+ builder.end();
+ return builder;
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/core/model/WorldModel.java b/src/main/java/com/jozufozu/flywheel/core/model/WorldModel.java
new file mode 100644
index 000000000..fa2001d0d
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/core/model/WorldModel.java
@@ -0,0 +1,53 @@
+package com.jozufozu.flywheel.core.model;
+
+import java.util.Collection;
+
+import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
+import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
+import com.jozufozu.flywheel.core.Formats;
+import com.jozufozu.flywheel.util.BufferBuilderReader;
+
+import net.minecraft.client.renderer.LightTexture;
+import net.minecraft.client.renderer.RenderType;
+import net.minecraft.world.IBlockDisplayReader;
+import net.minecraft.world.gen.feature.template.Template;
+
+public class WorldModel implements IModel {
+
+ private final BufferBuilderReader reader;
+
+ public WorldModel(IBlockDisplayReader renderWorld, RenderType layer, Collection blocks) {
+ reader = new BufferBuilderReader(ModelUtil.getBufferBuilderFromTemplate(renderWorld, layer, blocks));
+ }
+
+ @Override
+ public void buffer(VecBuffer vertices) {
+ for (int i = 0; i < vertexCount(); i++) {
+ vertices.putVec3(reader.getX(i), reader.getY(i), reader.getZ(i));
+
+ vertices.putVec3(reader.getNX(i), reader.getNY(i), reader.getNZ(i));
+
+ vertices.putVec2(reader.getU(i), reader.getV(i));
+
+ vertices.putColor(reader.getR(i), reader.getG(i), reader.getB(i), reader.getA(i));
+
+ int light = reader.getLight(i);
+
+ byte block = (byte) (LightTexture.block(light) << 4);
+ byte sky = (byte) (LightTexture.sky(light) << 4);
+
+ vertices.putVec2(block, sky);
+ }
+ }
+
+ @Override
+ public int vertexCount() {
+ return reader.getVertexCount();
+ }
+
+ @Override
+ public VertexFormat format() {
+ return Formats.COLORED_LIT_MODEL;
+ }
+
+}
diff --git a/src/main/java/com/jozufozu/flywheel/event/BeginFrameEvent.java b/src/main/java/com/jozufozu/flywheel/event/BeginFrameEvent.java
index 042cc1acd..a4c508328 100644
--- a/src/main/java/com/jozufozu/flywheel/event/BeginFrameEvent.java
+++ b/src/main/java/com/jozufozu/flywheel/event/BeginFrameEvent.java
@@ -5,6 +5,7 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LightTexture;
+import net.minecraft.client.renderer.culling.ClippingHelper;
import net.minecraft.client.world.ClientWorld;
import net.minecraftforge.eventbus.api.Event;
@@ -14,13 +15,15 @@ public class BeginFrameEvent extends Event {
private final ActiveRenderInfo info;
private final GameRenderer gameRenderer;
private final LightTexture lightTexture;
+ private final ClippingHelper clippingHelper;
- public BeginFrameEvent(ClientWorld world, MatrixStack stack, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture) {
+ public BeginFrameEvent(ClientWorld world, MatrixStack stack, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture, ClippingHelper clippingHelper) {
this.world = world;
this.stack = stack;
this.info = info;
this.gameRenderer = gameRenderer;
this.lightTexture = lightTexture;
+ this.clippingHelper = clippingHelper;
}
public ClientWorld getWorld() {
@@ -42,4 +45,8 @@ public class BeginFrameEvent extends Event {
public LightTexture getLightTexture() {
return lightTexture;
}
+
+ public ClippingHelper getClippingHelper() {
+ return clippingHelper;
+ }
}
diff --git a/src/main/java/com/jozufozu/flywheel/event/ReloadRenderersEvent.java b/src/main/java/com/jozufozu/flywheel/event/ReloadRenderersEvent.java
index dc7bac5fb..aad67e6fd 100644
--- a/src/main/java/com/jozufozu/flywheel/event/ReloadRenderersEvent.java
+++ b/src/main/java/com/jozufozu/flywheel/event/ReloadRenderersEvent.java
@@ -1,5 +1,7 @@
package com.jozufozu.flywheel.event;
+import javax.annotation.Nullable;
+
import net.minecraft.client.world.ClientWorld;
import net.minecraftforge.eventbus.api.Event;
@@ -10,6 +12,7 @@ public class ReloadRenderersEvent extends Event {
this.world = world;
}
+ @Nullable
public ClientWorld getWorld() {
return world;
}
diff --git a/src/main/java/com/jozufozu/flywheel/event/RenderLayerEvent.java b/src/main/java/com/jozufozu/flywheel/event/RenderLayerEvent.java
index a22816f71..e47f2886c 100644
--- a/src/main/java/com/jozufozu/flywheel/event/RenderLayerEvent.java
+++ b/src/main/java/com/jozufozu/flywheel/event/RenderLayerEvent.java
@@ -1,6 +1,13 @@
package com.jozufozu.flywheel.event;
+import javax.annotation.Nullable;
+
+import com.jozufozu.flywheel.backend.Backend;
+import com.jozufozu.flywheel.backend.state.RenderLayer;
+import com.mojang.blaze3d.matrix.MatrixStack;
+
import net.minecraft.client.renderer.RenderType;
+import net.minecraft.client.renderer.RenderTypeBuffers;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraftforge.eventbus.api.Event;
@@ -8,18 +15,36 @@ import net.minecraftforge.eventbus.api.Event;
public class RenderLayerEvent extends Event {
private final ClientWorld world;
public final RenderType type;
+ public final MatrixStack stack;
public final Matrix4f viewProjection;
+ public final RenderTypeBuffers buffers;
public final double camX;
public final double camY;
public final double camZ;
+ public final RenderLayer layer;
- public RenderLayerEvent(ClientWorld world, RenderType type, Matrix4f viewProjection, double camX, double camY, double camZ) {
+ public RenderLayerEvent(ClientWorld world, RenderType type, MatrixStack stack, RenderTypeBuffers buffers, double camX, double camY, double camZ) {
this.world = world;
this.type = type;
- this.viewProjection = viewProjection;
+ this.stack = stack;
+
+ viewProjection = stack.last()
+ .pose()
+ .copy();
+ viewProjection.multiplyBackward(Backend.getInstance()
+ .getProjectionMatrix());
+
+ this.buffers = buffers;
this.camX = camX;
this.camY = camY;
this.camZ = camZ;
+
+ this.layer = RenderLayer.fromRenderType(type);
+ }
+
+ @Nullable
+ public RenderLayer getLayer() {
+ return layer;
}
public ClientWorld getWorld() {
diff --git a/src/main/java/com/jozufozu/flywheel/event/package-info.java b/src/main/java/com/jozufozu/flywheel/event/package-info.java
new file mode 100644
index 000000000..b2b0463bf
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/event/package-info.java
@@ -0,0 +1,6 @@
+@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
+package com.jozufozu.flywheel.event;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
+import mcp.MethodsReturnNonnullByDefault;
diff --git a/src/main/java/com/jozufozu/flywheel/mixin/FastChunkProviderMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/FastChunkProviderMixin.java
index 9a1f3a0f9..28301ea18 100644
--- a/src/main/java/com/jozufozu/flywheel/mixin/FastChunkProviderMixin.java
+++ b/src/main/java/com/jozufozu/flywheel/mixin/FastChunkProviderMixin.java
@@ -1,6 +1,8 @@
package com.jozufozu.flywheel.mixin;
+import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@@ -8,7 +10,10 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+import com.jozufozu.flywheel.backend.Backend;
+
import net.minecraft.client.multiplayer.ClientChunkProvider;
+import net.minecraft.client.world.ClientWorld;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.PacketBuffer;
import net.minecraft.world.biome.BiomeContainer;
@@ -20,6 +25,9 @@ import net.minecraft.world.chunk.IChunk;
@Mixin(ClientChunkProvider.class)
public abstract class FastChunkProviderMixin extends AbstractChunkProvider {
+ @Shadow
+ @Final
+ private ClientWorld level;
@Unique
private int lastX;
@Unique
@@ -32,36 +40,52 @@ public abstract class FastChunkProviderMixin extends AbstractChunkProvider {
at = @At("HEAD"),
cancellable = true)
public void returnCachedChunk(int x, int z, ChunkStatus status, boolean create, CallbackInfoReturnable cir) {
- if (status.isOrAfter(ChunkStatus.FULL) && lastChunk != null && x == lastX && z == lastZ) {
- cir.setReturnValue(lastChunk);
+ if (Backend.getInstance().chunkCachingEnabled && status.isOrAfter(ChunkStatus.FULL)) {
+ synchronized (level) {
+ if (lastChunk != null && x == lastX && z == lastZ) {
+ cir.setReturnValue(lastChunk);
+ }
+ }
}
}
@Inject(method = "getChunk",
at = @At("RETURN"))
public void cacheChunk(int x, int z, ChunkStatus status, boolean create, CallbackInfoReturnable cir) {
- if (status.isOrAfter(ChunkStatus.FULL)) {
- lastChunk = cir.getReturnValue();
- lastX = x;
- lastZ = z;
+ if (Backend.getInstance().chunkCachingEnabled && status.isOrAfter(ChunkStatus.FULL)) {
+ synchronized (level) {
+ lastChunk = cir.getReturnValue();
+ lastX = x;
+ lastZ = z;
+ }
}
}
@Inject(method = "drop", at = @At("HEAD"))
public void invalidateOnDrop(int x, int z, CallbackInfo ci) {
- if (x == lastX && z == lastZ)
- lastChunk = null;
+ if (Backend.getInstance().chunkCachingEnabled) {
+ synchronized (level) {
+ if (x == lastX && z == lastZ) lastChunk = null;
+ }
+ }
}
@Inject(method = "replaceWithPacketData", at = @At("HEAD"))
public void invalidateOnPacket(int x, int z, BiomeContainer p_228313_3_, PacketBuffer p_228313_4_, CompoundNBT p_228313_5_, int p_228313_6_, boolean p_228313_7_, CallbackInfoReturnable cir) {
- if (x == lastX && z == lastZ)
- lastChunk = null;
+ if (Backend.getInstance().chunkCachingEnabled) {
+ synchronized (level) {
+ if (x == lastX && z == lastZ) lastChunk = null;
+ }
+ }
}
@Redirect(method = "isTickingChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientChunkProvider;hasChunk(II)Z"))
public boolean redirectTicking(ClientChunkProvider clientChunkProvider, int x, int z) {
- if (lastChunk != null && x == lastX && z == lastZ) return true;
+ if (Backend.getInstance().chunkCachingEnabled) {
+ synchronized (level) {
+ if (lastChunk != null && x == lastX && z == lastZ) return true;
+ }
+ }
return clientChunkProvider.hasChunk(x, z);
}
diff --git a/src/main/java/com/jozufozu/flywheel/mixin/GlobalClippingHelperMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/GlobalClippingHelperMixin.java
new file mode 100644
index 000000000..39958bbc0
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/mixin/GlobalClippingHelperMixin.java
@@ -0,0 +1,20 @@
+package com.jozufozu.flywheel.mixin;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import com.jozufozu.flywheel.core.Clipping;
+
+import net.minecraft.client.renderer.culling.ClippingHelper;
+import net.minecraft.util.math.vector.Matrix4f;
+
+@Mixin(ClippingHelper.class)
+public class GlobalClippingHelperMixin {
+
+ @Inject(at = @At("TAIL"), method = "")
+ private void init(Matrix4f p_i226026_1_, Matrix4f p_i226026_2_, CallbackInfo ci) {
+ Clipping.HELPER = (ClippingHelper) (Object) this;
+ }
+}
diff --git a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java
index 056efaa7b..80abdb73e 100644
--- a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java
+++ b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java
@@ -1,6 +1,7 @@
package com.jozufozu.flywheel.mixin;
import org.lwjgl.opengl.GL20;
+import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@@ -10,6 +11,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.OptifineHandler;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
+import com.jozufozu.flywheel.core.Clipping;
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
import com.jozufozu.flywheel.event.BeginFrameEvent;
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
@@ -21,6 +23,7 @@ import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.RenderType;
+import net.minecraft.client.renderer.RenderTypeBuffers;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.BlockPos;
@@ -37,9 +40,13 @@ public class RenderHooksMixin {
@Shadow
private ClientWorld level;
+ @Shadow
+ @Final
+ private RenderTypeBuffers renderBuffers;
+
@Inject(at = @At(value = "INVOKE", target = "net.minecraft.client.renderer.WorldRenderer.compileChunksUntil(J)V"), method = "renderLevel")
- private void setupFrame(MatrixStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f p_228426_9_, CallbackInfo ci) {
- MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(level, stack, info, gameRenderer, lightTexture));
+ private void setupFrame(MatrixStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projection, CallbackInfo ci) {
+ MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(level, stack, info, gameRenderer, lightTexture, Clipping.HELPER));
}
/**
@@ -49,15 +56,14 @@ public class RenderHooksMixin {
*/
@Inject(at = @At("TAIL"), method = "renderChunkLayer")
private void renderLayer(RenderType type, MatrixStack stack, double camX, double camY, double camZ, CallbackInfo ci) {
- Matrix4f view = stack.last()
- .pose();
- Matrix4f viewProjection = view.copy();
- viewProjection.multiplyBackward(Backend.getInstance()
- .getProjectionMatrix());
- MinecraftForge.EVENT_BUS.post(new RenderLayerEvent(level, type, viewProjection, camX, camY, camZ));
+ RenderTypeBuffers renderBuffers = this.renderBuffers;
+
+ MinecraftForge.EVENT_BUS.post(new RenderLayerEvent(level, type, stack, renderBuffers, camX, camY, camZ));
if (!OptifineHandler.usingShaders()) GL20.glUseProgram(0);
+
+ renderBuffers.bufferSource().endBatch(type);
}
@Inject(at = @At("TAIL"), method = "allChanged")
diff --git a/src/main/java/com/jozufozu/flywheel/util/Lazy.java b/src/main/java/com/jozufozu/flywheel/util/Lazy.java
index 344a07976..6bcbd9d23 100644
--- a/src/main/java/com/jozufozu/flywheel/util/Lazy.java
+++ b/src/main/java/com/jozufozu/flywheel/util/Lazy.java
@@ -36,6 +36,10 @@ public class Lazy {
return Pair.of(lazy, killSwitch);
}
+ public static Lazy of(NonNullSupplier factory) {
+ return new Lazy<>(factory);
+ }
+
public static class KillSwitch {
private final Lazy lazy;
diff --git a/src/main/java/com/jozufozu/flywheel/util/RenderMath.java b/src/main/java/com/jozufozu/flywheel/util/RenderMath.java
index 79028b953..3b891d683 100644
--- a/src/main/java/com/jozufozu/flywheel/util/RenderMath.java
+++ b/src/main/java/com/jozufozu/flywheel/util/RenderMath.java
@@ -2,7 +2,31 @@ package com.jozufozu.flywheel.util;
public class RenderMath {
+ /**
+ * Convert a signed, normalized floating point value into a normalized byte.
+ */
public static byte nb(float f) {
return (byte) (f * 127);
}
+
+ /**
+ * Convert a signed byte into a normalized float.
+ */
+ public static float f(byte b) {
+ return b / 127f;
+ }
+
+ /**
+ * Convert an unsigned byte into a normalized float.
+ */
+ public static float uf(byte b) {
+ return (float) (Byte.toUnsignedInt(b)) / 255f;
+ }
+
+ /**
+ * Convert an unsigned, normalized float into an unsigned normalized byte.
+ */
+ public static byte unb(float f) {
+ return (byte) Math.floor(f * 255);
+ }
}
diff --git a/src/main/java/com/jozufozu/flywheel/util/transform/QuaternionTransformStack.java b/src/main/java/com/jozufozu/flywheel/util/transform/QuaternionTransformStack.java
deleted file mode 100644
index 3e6908201..000000000
--- a/src/main/java/com/jozufozu/flywheel/util/transform/QuaternionTransformStack.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.jozufozu.flywheel.util.transform;
-
-import java.util.ArrayDeque;
-import java.util.Deque;
-
-import net.minecraft.util.math.vector.Quaternion;
-
-public class QuaternionTransformStack implements TransformStack {
-
- private final Deque stack;
-
- public QuaternionTransformStack() {
- stack = new ArrayDeque<>();
- stack.add(new Transform());
- }
-
- @Override
- public TransformStack translate(double x, double y, double z) {
-
- Transform peek = stack.peek();
-
- double qx = peek.qx;
- double qy = peek.qy;
- double qz = peek.qz;
- double qw = peek.qw;
- peek.x += qw * x + qy * z - qz * y;
- peek.y += qw * y - qx * z + qz * x;
- peek.z += qw * z + qx * y - qy * x;
-
- return this;
- }
-
- @Override
- public TransformStack multiply(Quaternion quaternion) {
- return this;
- }
-
- @Override
- public TransformStack push() {
- stack.push(stack.peek().copy());
- return this;
- }
-
- @Override
- public TransformStack scale(float factor) {
- return this;
- }
-
- @Override
- public TransformStack pop() {
-
- if (stack.size() == 1) {
- stack.peek().loadIdentity();
- } else {
- stack.pop();
- }
-
- return this;
- }
-
- private static class Transform {
- public double qx;
- public double qy;
- public double qz;
- public double qw;
- public double x;
- public double y;
- public double z;
-
- public Transform() {
- qw = 1.0;
- }
-
- public void loadIdentity() {
- x = y = z = 0.0;
-
- qx = qy = qz = 0.0;
- qw = 1.0;
- }
-
- public Transform copy() {
- Transform transform = new Transform();
-
- transform.qx = this.qx;
- transform.qy = this.qy;
- transform.qz = this.qz;
- transform.qw = this.qw;
- transform.x = this.x;
- transform.y = this.y;
- transform.z = this.z;
-
- return transform;
- }
- }
-}
diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml
index 5be2bde90..5ceeaca9b 100644
--- a/src/main/resources/META-INF/mods.toml
+++ b/src/main/resources/META-INF/mods.toml
@@ -1,7 +1,7 @@
modLoader = "javafml"
loaderVersion = "[36,)"
issueTrackerURL = "https://github.com/Jozufozu/Flywheel/issues"
-license = "LGPLv3"
+license = "MIT"
[[mods]]
modId = "flywheel"
diff --git a/src/main/resources/flywheel.mixins.json b/src/main/resources/flywheel.mixins.json
index 2c4db2153..1959046f5 100644
--- a/src/main/resources/flywheel.mixins.json
+++ b/src/main/resources/flywheel.mixins.json
@@ -18,7 +18,8 @@
"atlas.SheetDataAccessor",
"light.LightUpdateMixin",
"light.NetworkLightUpdateMixin",
- "FastChunkProviderMixin"
+ "FastChunkProviderMixin",
+ "GlobalClippingHelperMixin"
],
"injectors": {
"defaultRequire": 0