diff --git a/src/main/java/com/jozufozu/flywheel/api/vertex/ShadedVertexList.java b/src/main/java/com/jozufozu/flywheel/api/vertex/ShadedVertexList.java new file mode 100644 index 000000000..227879b3a --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/api/vertex/ShadedVertexList.java @@ -0,0 +1,5 @@ +package com.jozufozu.flywheel.api.vertex; + +public interface ShadedVertexList extends VertexList { + boolean isShaded(int index); +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java index 73ea3e1c5..bd85a26b8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java @@ -44,7 +44,7 @@ public class InstancedMaterialGroup
implements MaterialG
.onAMDWindows()) {
this.allocator = FallbackAllocator.INSTANCE;
} else {
- this.allocator = new ModelPool(Formats.POS_TEX_NORMAL, 2048);
+ this.allocator = new ModelPool(Formats.POS_TEX_NORMAL);
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/BufferBuilderExtension.java b/src/main/java/com/jozufozu/flywheel/backend/model/BufferBuilderExtension.java
index 87d840792..4aec62268 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/model/BufferBuilderExtension.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/model/BufferBuilderExtension.java
@@ -12,6 +12,8 @@ import com.mojang.blaze3d.vertex.VertexFormat;
*/
public interface BufferBuilderExtension {
+ int flywheel$getVertices();
+
/**
* Frees the internal ByteBuffer, if it exists.
*/
@@ -24,4 +26,12 @@ public interface BufferBuilderExtension {
* @param vertexCount The number of vertices in the buffer.
*/
void flywheel$injectForRender(ByteBuffer buffer, VertexFormat format, int vertexCount);
+
+ /**
+ * Appends the remaining bytes from the given buffer to this BufferBuilder.
+ * @param buffer The buffer from which to copy bytes.
+ * @throws IllegalStateException If this BufferBuilder is not started or is the process of writing a vertex
+ * @throws IllegalArgumentException If the given buffer does not contain a whole number of vertices
+ */
+ void flywheel$appendBufferUnsafe(ByteBuffer buffer);
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java b/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java
index 7e50a5ddc..5c1d426c7 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java
@@ -35,16 +35,14 @@ public class ModelPool implements ModelAllocator {
* Create a new model pool.
*
* @param vertexType The vertex type of the models that will be stored in the pool.
- * @param initialSize The initial size of the pool, in vertices.
*/
- public ModelPool(VertexType vertexType, int initialSize) {
+ public ModelPool(VertexType vertexType) {
this.vertexType = vertexType;
int stride = vertexType.getStride();
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
vbo.bind();
- vbo.ensureCapacity((long) stride * initialSize);
vbo.setGrowthMargin(stride * 64);
}
diff --git a/src/main/java/com/jozufozu/flywheel/core/Templates.java b/src/main/java/com/jozufozu/flywheel/core/Templates.java
index 59b538a2f..30987940b 100644
--- a/src/main/java/com/jozufozu/flywheel/core/Templates.java
+++ b/src/main/java/com/jozufozu/flywheel/core/Templates.java
@@ -1,13 +1,18 @@
package com.jozufozu.flywheel.core;
+import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
import com.jozufozu.flywheel.core.compile.FragmentTemplateData;
import com.jozufozu.flywheel.core.compile.InstancingTemplateData;
import com.jozufozu.flywheel.core.compile.OneShotTemplateData;
import com.jozufozu.flywheel.core.compile.Template;
+import com.jozufozu.flywheel.core.source.FileResolution;
+import com.jozufozu.flywheel.core.source.Resolver;
public class Templates {
+ public static final FileResolution DIFFUSE_FILE = Resolver.INSTANCE.get(Flywheel.rl("core/diffuse.glsl"));
+
public static final Template
{@code - * IModel model = ...; + * Model model = ...; * VecBuffer into = ...; * * int initial = VecBuffer.unwrap().position(); diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ModelTransformer.java b/src/main/java/com/jozufozu/flywheel/core/model/ModelTransformer.java index 10eafd1c4..52e542ec7 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/ModelTransformer.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelTransformer.java @@ -1,5 +1,8 @@ package com.jozufozu.flywheel.core.model; +import java.util.function.IntPredicate; + +import com.jozufozu.flywheel.api.vertex.ShadedVertexList; import com.jozufozu.flywheel.api.vertex.VertexList; import com.jozufozu.flywheel.util.DiffuseLightCalculator; import com.jozufozu.flywheel.util.transform.Transform; @@ -19,12 +22,18 @@ public class ModelTransformer { private final Model model; private final VertexList reader; + private final IntPredicate shadedPredicate; public final Context context = new Context(); public ModelTransformer(Model model) { this.model = model; reader = model.getReader(); + if (reader instanceof ShadedVertexList shaded) { + shadedPredicate = shaded::isShaded; + } else { + shadedPredicate = index -> true; + } } public void renderInto(Params params, PoseStack input, VertexConsumer builder) { @@ -82,7 +91,7 @@ public class ModelTransformer { a = reader.getA(i); } if (context.outputColorDiffuse) { - float instanceDiffuse = diffuseCalculator.getDiffuse(nx, ny, nz); + float instanceDiffuse = diffuseCalculator.getDiffuse(nx, ny, nz, shadedPredicate.test(i)); int colorR = transformColor(r, instanceDiffuse); int colorG = transformColor(g, instanceDiffuse); int colorB = transformColor(b, instanceDiffuse); 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 9e711d61a..34c2e05e1 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java @@ -30,25 +30,53 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; public class ModelUtil { - public static BufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack ms) { + + private static final ThreadLocalTHREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new); + + public static ShadeSeparatedBufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack poseStack) { + return getBufferBuilder(VirtualEmptyBlockGetter.INSTANCE, model, referenceState, poseStack); + } + + public static ShadeSeparatedBufferBuilder getBufferBuilder(BlockAndTintGetter renderWorld, BakedModel model, BlockState referenceState, PoseStack poseStack) { ModelBlockRenderer blockRenderer = Minecraft.getInstance().getBlockRenderer().getModelRenderer(); - BufferBuilder builder = new BufferBuilder(512); + ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get(); + + ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper; + ShadeSeparatedBufferBuilder builder = new ShadeSeparatedBufferBuilder(512); + BufferBuilder unshadedBuilder = objects.unshadedBuilder; + builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); + unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); + shadeSeparatingWrapper.prepare(builder, unshadedBuilder); model = DefaultLayerFilteringBakedModel.wrap(model); - blockRenderer.tesselateBlock(VirtualEmptyBlockGetter.INSTANCE, model, referenceState, BlockPos.ZERO, ms, builder, - false, new Random(), 42, OverlayTexture.NO_OVERLAY); + model = shadeSeparatingWrapper.wrapModel(model); + blockRenderer.tesselateBlock(renderWorld, model, referenceState, BlockPos.ZERO, poseStack, shadeSeparatingWrapper, + false, objects.random, 42, OverlayTexture.NO_OVERLAY); + shadeSeparatingWrapper.clear(); + unshadedBuilder.end(); + builder.appendUnshadedVertices(unshadedBuilder); builder.end(); + return builder; } - public static BufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection blocks) { - BlockRenderDispatcher dispatcher = Minecraft.getInstance().getBlockRenderer(); - ModelBlockRenderer modelRenderer = dispatcher.getModelRenderer(); + public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection blocks) { + return getBufferBuilderFromTemplate(renderWorld, layer, blocks, new PoseStack()); + } + + public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection blocks, PoseStack poseStack) { + BlockRenderDispatcher dispatcher = Minecraft.getInstance().getBlockRenderer(); + ModelBlockRenderer modelRenderer = dispatcher.getModelRenderer(); + ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get(); + + Random random = objects.random; + ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper; + ShadeSeparatedBufferBuilder builder = new ShadeSeparatedBufferBuilder(512); + BufferBuilder unshadedBuilder = objects.unshadedBuilder; - PoseStack ms = new PoseStack(); - Random random = new Random(); - BufferBuilder builder = new BufferBuilder(512); builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); + unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); + shadeSeparatingWrapper.prepare(builder, unshadedBuilder); ModelBlockRenderer.enableCaching(); for (StructureTemplate.StructureBlockInfo info : blocks) { @@ -65,19 +93,24 @@ public class ModelUtil { } else { model = CullingBakedModel.wrap(model); model = LayerFilteringBakedModel.wrap(model, layer); + model = shadeSeparatingWrapper.wrapModel(model); } BlockPos pos = info.pos; - ms.pushPose(); - ms.translate(pos.getX(), pos.getY(), pos.getZ()); - modelRenderer.tesselateBlock(renderWorld, model, state, pos, ms, builder, + poseStack.pushPose(); + poseStack.translate(pos.getX(), pos.getY(), pos.getZ()); + modelRenderer.tesselateBlock(renderWorld, model, state, pos, poseStack, shadeSeparatingWrapper, true, random, 42, OverlayTexture.NO_OVERLAY); - ms.popPose(); + poseStack.popPose(); } ModelBlockRenderer.clearCache(); + shadeSeparatingWrapper.clear(); + unshadedBuilder.end(); + builder.appendUnshadedVertices(unshadedBuilder); builder.end(); + return builder; } @@ -91,4 +124,10 @@ public class ModelUtil { return stack; }; } + + private static class ThreadLocalObjects { + public final Random random = new Random(); + public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer(); + public final BufferBuilder unshadedBuilder = new BufferBuilder(512); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferBuilder.java new file mode 100644 index 000000000..e7ca9f064 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferBuilder.java @@ -0,0 +1,28 @@ +package com.jozufozu.flywheel.core.model; + +import java.nio.ByteBuffer; + +import com.jozufozu.flywheel.backend.model.BufferBuilderExtension; +import com.jozufozu.flywheel.fabric.helper.BufferBuilderHelper; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.datafixers.util.Pair; + +public class ShadeSeparatedBufferBuilder extends BufferBuilder { + protected int unshadedStartVertex; + + public ShadeSeparatedBufferBuilder(int capacity) { + super(capacity); + } + + public void appendUnshadedVertices(BufferBuilder unshadedBuilder) { + Pair data = unshadedBuilder.popNextBuffer(); + ByteBuffer buffer = data.getSecond(); + BufferBuilderHelper.fixByteOrder(unshadedBuilder, buffer); + unshadedStartVertex = ((BufferBuilderExtension) this).flywheel$getVertices(); + ((BufferBuilderExtension) this).flywheel$appendBufferUnsafe(buffer); + } + + public int getUnshadedStartVertex() { + return unshadedStartVertex; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatingVertexConsumer.java b/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatingVertexConsumer.java new file mode 100644 index 000000000..307ffbbd3 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatingVertexConsumer.java @@ -0,0 +1,122 @@ +package com.jozufozu.flywheel.core.model; + +import java.util.Random; +import java.util.function.Supplier; + +import com.jozufozu.flywheel.fabric.model.FabricModelUtil; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; + +public class ShadeSeparatingVertexConsumer implements VertexConsumer { + private final ShadeSeparatingBakedModel modelWrapper = new ShadeSeparatingBakedModel(); + protected VertexConsumer shadedConsumer; + protected VertexConsumer unshadedConsumer; + protected VertexConsumer activeConsumer; + + public void prepare(VertexConsumer shadedConsumer, VertexConsumer unshadedConsumer) { + this.shadedConsumer = shadedConsumer; + this.unshadedConsumer = unshadedConsumer; + } + + public void clear() { + shadedConsumer = null; + unshadedConsumer = null; + activeConsumer = null; + } + + public BakedModel wrapModel(BakedModel model) { + modelWrapper.setWrapped(model); + return modelWrapper; + } + + protected void setActiveConsumer(boolean shaded) { + activeConsumer = shaded ? shadedConsumer : unshadedConsumer; + } + + @Override + public void putBulkData(PoseStack.Pose poseEntry, BakedQuad quad, float[] colorMuls, float red, float green, float blue, int[] combinedLights, int combinedOverlay, boolean mulColor) { + if (quad.isShade()) { + shadedConsumer.putBulkData(poseEntry, quad, colorMuls, red, green, blue, combinedLights, combinedOverlay, mulColor); + } else { + unshadedConsumer.putBulkData(poseEntry, quad, colorMuls, red, green, blue, combinedLights, combinedOverlay, mulColor); + } + } + + @Override + public VertexConsumer vertex(double x, double y, double z) { + activeConsumer.vertex(x, y, z); + return this; + } + + @Override + public VertexConsumer color(int red, int green, int blue, int alpha) { + activeConsumer.color(red, green, blue, alpha); + return this; + } + + @Override + public VertexConsumer uv(float u, float v) { + activeConsumer.uv(u, v); + return this; + } + + @Override + public VertexConsumer overlayCoords(int u, int v) { + activeConsumer.overlayCoords(u, v); + return this; + } + + @Override + public VertexConsumer uv2(int u, int v) { + activeConsumer.uv2(u, v); + return this; + } + + @Override + public VertexConsumer normal(float x, float y, float z) { + activeConsumer.normal(x, y, z); + return this; + } + + @Override + public void endVertex() { + activeConsumer.endVertex(); + } + + @Override + public void defaultColor(int red, int green, int blue, int alpha) { + activeConsumer.defaultColor(red, green, blue, alpha); + } + + @Override + public void unsetDefaultColor() { + activeConsumer.unsetDefaultColor(); + } + + private class ShadeSeparatingBakedModel extends ForwardingBakedModel { + private final QuadTransform quadTransform = quad -> { + ShadeSeparatingVertexConsumer.this.setActiveConsumer(FabricModelUtil.isShaded(quad)); + return true; + }; + + private void setWrapped(BakedModel model) { + wrapped = model; + } + + @Override + public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { + context.pushTransform(quadTransform); + super.emitBlockQuads(blockView, state, pos, randomSupplier, context); + context.popTransform(); + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java index ddf552509..ff218762a 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java @@ -6,6 +6,7 @@ import com.jozufozu.flywheel.api.vertex.VertexList; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.layout.CommonItems; +import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder; import com.jozufozu.flywheel.fabric.helper.BufferBuilderHelper; import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; @@ -58,6 +59,10 @@ Vertex FLWCreateVertex() { """; } + public BlockVertexListUnsafe.Shaded createReader(ByteBuffer buffer, int vertexCount, int unshadedStartVertex) { + return new BlockVertexListUnsafe.Shaded(buffer, vertexCount, unshadedStartVertex); + } + public VertexList createReader(BufferBuilder bufferBuilder) { // TODO: try to avoid virtual model rendering Pair pair = bufferBuilder.popNextBuffer(); @@ -69,6 +74,10 @@ Vertex FLWCreateVertex() { ByteBuffer buffer = pair.getSecond(); BufferBuilderHelper.fixByteOrder(bufferBuilder, buffer); - return new BlockVertexListUnsafe(buffer, drawState.vertexCount()); + if (bufferBuilder instanceof ShadeSeparatedBufferBuilder separated) { + return createReader(buffer, drawState.vertexCount(), separated.getUnshadedStartVertex()); + } else { + return createReader(buffer, drawState.vertexCount()); + } } } diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java index d12281dbf..57e0d0c25 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java @@ -2,7 +2,9 @@ package com.jozufozu.flywheel.core.vertex; import java.nio.ByteBuffer; +import com.jozufozu.flywheel.api.vertex.ShadedVertexList; import com.jozufozu.flywheel.api.vertex.VertexList; +import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder; import com.jozufozu.flywheel.fabric.helper.BufferBuilderHelper; import com.jozufozu.flywheel.util.RenderMath; import com.mojang.blaze3d.vertex.BufferBuilder; @@ -106,4 +108,20 @@ public class BlockVertexList implements VertexList { return vertexCount; } + public static class Shaded extends BlockVertexList implements ShadedVertexList { + + private final int unshadedStartVertex; + + public Shaded(ShadeSeparatedBufferBuilder builder) { + super(builder); + unshadedStartVertex = builder.getUnshadedStartVertex(); + } + + @Override + public boolean isShaded(int index) { + return index < unshadedStartVertex; + } + + } + } diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexListUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexListUnsafe.java index 7c93b29d6..0993f29e5 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexListUnsafe.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexListUnsafe.java @@ -4,6 +4,7 @@ import java.nio.ByteBuffer; import org.lwjgl.system.MemoryUtil; +import com.jozufozu.flywheel.api.vertex.ShadedVertexList; import com.jozufozu.flywheel.api.vertex.VertexList; import com.jozufozu.flywheel.util.RenderMath; @@ -97,4 +98,21 @@ public class BlockVertexListUnsafe implements VertexList { public int getVertexCount() { return vertexCount; } + + public static class Shaded extends BlockVertexListUnsafe implements ShadedVertexList { + + private final int unshadedStartVertex; + + public Shaded(ByteBuffer buffer, int vertexCount, int unshadedStartVertex) { + super(buffer, vertexCount); + this.unshadedStartVertex = unshadedStartVertex; + } + + @Override + public boolean isShaded(int index) { + return index < unshadedStartVertex; + } + + } + } diff --git a/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualEmptyBlockGetter.java b/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualEmptyBlockGetter.java index 8058bcf68..ebfbe9389 100644 --- a/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualEmptyBlockGetter.java +++ b/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualEmptyBlockGetter.java @@ -22,115 +22,119 @@ import net.minecraft.world.level.lighting.LevelLightEngine; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.Fluids; -public enum VirtualEmptyBlockGetter implements BlockAndTintGetter { - INSTANCE; - - private final LevelLightEngine lightEngine = new LevelLightEngine(new LightChunkGetter() { - @Override - public BlockGetter getChunkForLighting(int p_63023_, int p_63024_) { - return VirtualEmptyBlockGetter.this; - } - - @Override - public BlockGetter getLevel() { - return VirtualEmptyBlockGetter.this; - } - }, false, false) { - private static final LayerLightEventListener SKY_DUMMY_LISTENER = new LayerLightEventListener() { - @Override - public void checkBlock(BlockPos pos) { - } - - @Override - public void onBlockEmissionIncrease(BlockPos pos, int p_164456_) { - } - - @Override - public boolean hasLightWork() { - return false; - } - - @Override - public int runUpdates(int p_164449_, boolean p_164450_, boolean p_164451_) { - return p_164449_; - } - - @Override - public void updateSectionStatus(SectionPos pos, boolean p_75838_) { - } - - @Override - public void enableLightSources(ChunkPos pos, boolean p_164453_) { - } - - @Override - public DataLayer getDataLayerData(SectionPos pos) { - return null; - } - - @Override - public int getLightValue(BlockPos pos) { - return 15; - } - }; - - @Override - public LayerLightEventListener getLayerListener(LightLayer layer) { - if (layer == LightLayer.BLOCK) { - return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE; - } else { - return SKY_DUMMY_LISTENER; - } - } - - @Override - public int getRawBrightness(BlockPos pos, int skyDarken) { - return 15 - skyDarken; - } - }; +public interface VirtualEmptyBlockGetter extends BlockAndTintGetter { + public static final VirtualEmptyBlockGetter INSTANCE = new StaticLightImpl(0, 15); + public static final VirtualEmptyBlockGetter FULL_BRIGHT = new StaticLightImpl(15, 15); + public static final VirtualEmptyBlockGetter FULL_DARK = new StaticLightImpl(0, 0); public static boolean is(BlockAndTintGetter blockGetter) { - return blockGetter == INSTANCE; + return blockGetter instanceof VirtualEmptyBlockGetter; } @Override - public BlockEntity getBlockEntity(BlockPos pos) { + default BlockEntity getBlockEntity(BlockPos pos) { return null; } @Override - public BlockState getBlockState(BlockPos pos) { + default BlockState getBlockState(BlockPos pos) { return Blocks.AIR.defaultBlockState(); } @Override - public FluidState getFluidState(BlockPos pos) { + default FluidState getFluidState(BlockPos pos) { return Fluids.EMPTY.defaultFluidState(); } @Override - public int getHeight() { + default int getHeight() { return 1; } @Override - public int getMinBuildHeight() { + default int getMinBuildHeight() { return 0; } @Override - public float getShade(Direction direction, boolean bool) { + default float getShade(Direction direction, boolean shaded) { return 1f; } @Override - public LevelLightEngine getLightEngine() { - return lightEngine; - } - - @Override - public int getBlockTint(BlockPos pos, ColorResolver resolver) { + default int getBlockTint(BlockPos pos, ColorResolver resolver) { Biome plainsBiome = Minecraft.getInstance().getConnection().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getOrThrow(Biomes.PLAINS); return resolver.getColor(plainsBiome, pos.getX(), pos.getZ()); } + + public static class StaticLightImpl implements VirtualEmptyBlockGetter { + private final LevelLightEngine lightEngine; + + public StaticLightImpl(int blockLight, int skyLight) { + lightEngine = new LevelLightEngine(new LightChunkGetter() { + @Override + public BlockGetter getChunkForLighting(int p_63023_, int p_63024_) { + return StaticLightImpl.this; + } + + @Override + public BlockGetter getLevel() { + return StaticLightImpl.this; + } + }, false, false) { + private final LayerLightEventListener blockListener = createStaticListener(blockLight); + private final LayerLightEventListener skyListener = createStaticListener(skyLight); + + @Override + public LayerLightEventListener getLayerListener(LightLayer layer) { + return layer == LightLayer.BLOCK ? blockListener : skyListener; + } + }; + } + + private static LayerLightEventListener createStaticListener(int light) { + return new LayerLightEventListener() { + @Override + public void checkBlock(BlockPos pos) { + } + + @Override + public void onBlockEmissionIncrease(BlockPos pos, int p_164456_) { + } + + @Override + public boolean hasLightWork() { + return false; + } + + @Override + public int runUpdates(int p_164449_, boolean p_164450_, boolean p_164451_) { + return p_164449_; + } + + @Override + public void updateSectionStatus(SectionPos pos, boolean p_75838_) { + } + + @Override + public void enableLightSources(ChunkPos pos, boolean p_164453_) { + } + + @Override + public DataLayer getDataLayerData(SectionPos pos) { + return null; + } + + @Override + public int getLightValue(BlockPos pos) { + return light; + } + }; + } + + @Override + public LevelLightEngine getLightEngine() { + return lightEngine; + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/fabric/model/FabricModelUtil.java b/src/main/java/com/jozufozu/flywheel/fabric/model/FabricModelUtil.java index 5c9044a00..5f490517c 100644 --- a/src/main/java/com/jozufozu/flywheel/fabric/model/FabricModelUtil.java +++ b/src/main/java/com/jozufozu/flywheel/fabric/model/FabricModelUtil.java @@ -6,9 +6,12 @@ import com.jozufozu.flywheel.Flywheel; import io.vram.frex.api.material.MaterialConstants; import io.vram.frex.fabric.compat.FabricMaterial; +import io.vram.frex.fabric.compat.FabricQuadView; import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; import net.fabricmc.fabric.impl.client.indigo.renderer.RenderMaterialImpl; +import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.QuadViewImpl; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.RenderType; @@ -19,6 +22,7 @@ public class FabricModelUtil { public static final boolean FREX_LOADED = FabricLoader.getInstance().isModLoaded("frex"); private static final BlendModeGetter BLEND_MODE_GETTER = createBlendModeGetter(); + private static final ShadedPredicate SHADED_PREDICATE = createShadedPredicate(); private static BlendModeGetter createBlendModeGetter() { if (FREX_LOADED) { @@ -50,7 +54,7 @@ public class FabricModelUtil { return BlendMode.DEFAULT; }; } catch (Exception e) { - Flywheel.LOGGER.error("Detected FREX but failed to load wrapper field.", e); + Flywheel.LOGGER.error("Detected FREX but failed to load material wrapper field.", e); return material -> BlendMode.DEFAULT; } } else if (INDIUM_LOADED) { @@ -60,10 +64,38 @@ public class FabricModelUtil { } } + private static ShadedPredicate createShadedPredicate() { + if (FREX_LOADED) { + try { + Field frexQuadViewField = FabricQuadView.class.getDeclaredField("wrapped"); + frexQuadViewField.setAccessible(true); + return quad -> { + try { + io.vram.frex.api.mesh.QuadView frexQuadView = (io.vram.frex.api.mesh.QuadView) frexQuadViewField.get(quad); + return !frexQuadView.material().disableDiffuse(); + } catch (Exception e) { + } + return true; + }; + } catch (Exception e) { + Flywheel.LOGGER.error("Detected FREX but failed to load quad view wrapper field.", e); + return quad -> true; + } + } else if (INDIUM_LOADED) { + return quad -> ((link.infra.indium.renderer.mesh.QuadViewImpl) quad).hasShade(); + } else { + return quad -> ((QuadViewImpl) quad).hasShade(); + } + } + public static BlendMode getBlendMode(RenderMaterial material) { return BLEND_MODE_GETTER.getBlendMode(material); } + public static boolean isShaded(QuadView quad) { + return SHADED_PREDICATE.isShaded(quad); + } + public static boolean doesLayerMatch(BlockState modelState, RenderType layer) { return ItemBlockRenderTypes.getChunkRenderType(modelState) == layer; } @@ -71,4 +103,8 @@ public class FabricModelUtil { private interface BlendModeGetter { BlendMode getBlendMode(RenderMaterial material); } + + private interface ShadedPredicate { + boolean isShaded(QuadView quad); + } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java index 6b13b9a92..bc82deaf8 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java @@ -20,16 +20,10 @@ public abstract class BufferBuilderMixin implements BufferBuilderExtension { private ByteBuffer buffer; @Shadow - private boolean building; + private int nextElementByte; @Shadow - public abstract void begin(VertexFormat.Mode p_166780_, VertexFormat p_166781_); - - @Shadow - private VertexFormat.Mode mode; - - @Shadow - private VertexFormat format; + private int vertices; @Shadow @Nullable @@ -39,7 +33,22 @@ public abstract class BufferBuilderMixin implements BufferBuilderExtension { private int elementIndex; @Shadow - private int vertices; + private VertexFormat format; + + @Shadow + private VertexFormat.Mode mode; + + @Shadow + private boolean building; + + @Shadow + private void ensureCapacity(int increaseAmount) { + } + + @Override + public int flywheel$getVertices() { + return vertices; + } @Override public void flywheel$freeBuffer() { @@ -61,4 +70,29 @@ public abstract class BufferBuilderMixin implements BufferBuilderExtension { this.currentElement = this.format.getElements().get(0); this.elementIndex = 0; } + + @Override + public void flywheel$appendBufferUnsafe(ByteBuffer buffer) { + if (!building) { + throw new IllegalStateException("BufferBuilder not started"); + } + if (elementIndex != 0) { + throw new IllegalStateException("Cannot append buffer while building vertex"); + } + + int numBytes = buffer.remaining(); + if (numBytes % format.getVertexSize() != 0) { + throw new IllegalArgumentException("Cannot append buffer with non-whole number of vertices"); + } + int numVertices = numBytes / format.getVertexSize(); + + ensureCapacity(numBytes + format.getVertexSize()); + int originalPosition = this.buffer.position(); + this.buffer.position(nextElementByte); + MemoryUtil.memCopy(buffer, this.buffer); + this.buffer.position(originalPosition); + + nextElementByte += numBytes; + vertices += numVertices; + } } diff --git a/src/main/java/com/jozufozu/flywheel/util/DiffuseLightCalculator.java b/src/main/java/com/jozufozu/flywheel/util/DiffuseLightCalculator.java index 4fc5eeaf4..4f1ac0557 100644 --- a/src/main/java/com/jozufozu/flywheel/util/DiffuseLightCalculator.java +++ b/src/main/java/com/jozufozu/flywheel/util/DiffuseLightCalculator.java @@ -15,5 +15,5 @@ public interface DiffuseLightCalculator { return level.effects().constantAmbientLight() ? NETHER : DEFAULT; } - float getDiffuse(float normalX, float normalY, float normalZ); + float getDiffuse(float normalX, float normalY, float normalZ, boolean shaded); } diff --git a/src/main/java/com/jozufozu/flywheel/util/RenderMath.java b/src/main/java/com/jozufozu/flywheel/util/RenderMath.java index 9244d91f4..16d223a8f 100644 --- a/src/main/java/com/jozufozu/flywheel/util/RenderMath.java +++ b/src/main/java/com/jozufozu/flywheel/util/RenderMath.java @@ -68,11 +68,17 @@ public class RenderMath { return (float) (((((target - current) % 360) + 540) % 360) - 180); } - public static float diffuseLight(float x, float y, float z) { + public static float diffuseLight(float x, float y, float z, boolean shaded) { + if (!shaded) { + return 1f; + } return Math.min(x * x * 0.6f + y * y * ((3f + y) / 4f) + z * z * 0.8f, 1f); } - public static float diffuseLightNether(float x, float y, float z) { + public static float diffuseLightNether(float x, float y, float z, boolean shaded) { + if (!shaded) { + return 0.9f; + } return Math.min(x * x * 0.6f + y * y * 0.9f + z * z * 0.8f, 1f); } } diff --git a/src/main/java/com/jozufozu/flywheel/util/TextureBinder.java b/src/main/java/com/jozufozu/flywheel/util/TextureBinder.java deleted file mode 100644 index e90435078..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/TextureBinder.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.jozufozu.flywheel.util; - -import net.minecraft.client.renderer.RenderType; - -/** - * This is a silly hack that's needed because flywheel does things too different from vanilla. - * - * - * When a {@link RenderType} is setup, the associated textures are "bound" within RenderSystem, but not actually - * bound via opengl. This class provides a helper function to forward the bindings to opengl. - *
- */ -public class TextureBinder { - -} diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling.glsl b/src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling.glsl index 958941126..423977c8a 100644 --- a/src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling.glsl +++ b/src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling.glsl @@ -1,5 +1,4 @@ #use "flywheel:context/fog.glsl" -#use "flywheel:core/diffuse.glsl" uniform float uTime; uniform mat4 uViewProjection; diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/context/world.glsl b/src/main/resources/assets/flywheel/flywheel/shaders/context/world.glsl index 28e36ab3d..b6386e92d 100644 --- a/src/main/resources/assets/flywheel/flywheel/shaders/context/world.glsl +++ b/src/main/resources/assets/flywheel/flywheel/shaders/context/world.glsl @@ -1,5 +1,4 @@ #use "flywheel:context/fog.glsl" -#use "flywheel:core/diffuse.glsl" uniform float uTime; uniform mat4 uViewProjection;