diff --git a/build.gradle b/build.gradle index 03f6f37b4..8fd354ad3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ buildscript { repositories { - maven { url = 'https://files.minecraftforge.net/maven' } + maven { url = 'https://maven.minecraftforge.net' } jcenter() mavenCentral() maven { url = 'https://repo.spongepowered.org/repository/maven-public/' } @@ -15,6 +15,7 @@ plugins { } apply plugin: 'net.minecraftforge.gradle' +apply plugin: 'eclipse' apply plugin: 'maven-publish' apply plugin: 'org.spongepowered.mixin' diff --git a/gradle.properties b/gradle.properties index 67be8fc69..224c737c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,11 +1,14 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false # mod version info -mod_version=0.1.1 +mod_version=0.2.0 mc_update_version=1.16 minecraft_version=1.16.5 -forge_version=36.0.42 -mcp_mappings=20200920-mixed-1.16.3 +forge_version=36.1.66 + +# curseforge info projectId=486392 curse_type=beta + +# github info github_project=Jozufozu/Flywheel diff --git a/src/main/java/com/jozufozu/flywheel/Flywheel.java b/src/main/java/com/jozufozu/flywheel/Flywheel.java index 6dbfa058e..fb80e35c0 100644 --- a/src/main/java/com/jozufozu/flywheel/Flywheel.java +++ b/src/main/java/com/jozufozu/flywheel/Flywheel.java @@ -1,8 +1,5 @@ package com.jozufozu.flywheel; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - import com.jozufozu.flywheel.config.FlwCommands; import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.config.FlwPackets; @@ -18,7 +15,6 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; public class Flywheel { public static final String ID = "flywheel"; - private static final Logger LOGGER = LogManager.getLogger(); public Flywheel() { FMLJavaModLoadingContext.get() diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index 239aedf01..0cfb51552 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -15,7 +15,7 @@ import org.lwjgl.opengl.GLCapabilities; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; import com.jozufozu.flywheel.backend.instancing.InstanceData; -import com.jozufozu.flywheel.backend.instancing.MaterialSpec; +import com.jozufozu.flywheel.backend.material.MaterialSpec; import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java b/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java index e8793bf95..a81a8f520 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java +++ b/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java @@ -28,13 +28,13 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; -import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.loading.Shader; import com.jozufozu.flywheel.backend.loading.ShaderLoadingException; import com.jozufozu.flywheel.backend.pipeline.SourceFile; import com.jozufozu.flywheel.backend.pipeline.WorldShaderPipeline; import com.jozufozu.flywheel.core.shader.WorldProgram; +import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.event.GatherContextEvent; import com.mojang.blaze3d.systems.RenderSystem; diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/GlTextureUnit.java b/src/main/java/com/jozufozu/flywheel/backend/gl/GlTextureUnit.java new file mode 100644 index 000000000..fbd28c63a --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/GlTextureUnit.java @@ -0,0 +1,54 @@ +package com.jozufozu.flywheel.backend.gl; + +import static org.lwjgl.opengl.GL13.GL_TEXTURE0; + +import com.mojang.blaze3d.platform.GlStateManager; + +public enum GlTextureUnit { + T0(0), + T1(1), + T2(2), + T3(3), + T4(4), + T5(5), + T6(6), + T7(7), + T8(8), + T9(9), + T10(10), + T11(11), + T12(12), + T13(13), + T14(14), + T15(15), + T16(16), + T17(17), + T18(18), + T19(19), + T20(20), + T21(21), + T22(22), + T23(23), + T24(24), + T25(25), + T26(26), + T27(27), + T28(28), + T29(29), + T30(30), + T31(31), + + ; + + public final int number; + public final int glEnum; + + GlTextureUnit(int unit) { + this.number = unit; + this.glEnum = GL_TEXTURE0 + unit; + } + + public void makeActive() { + GlStateManager._activeTexture(glEnum); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/VecBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/VecBuffer.java index 801dab17a..22092e6ca 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/VecBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/VecBuffer.java @@ -89,6 +89,14 @@ public class VecBuffer { return this; } + public VecBuffer putColor(int r, int g, int b, int a) { + internal.put((byte) r); + internal.put((byte) g); + internal.put((byte) b); + internal.put((byte) a); + return this; + } + public VecBuffer putVec3(float x, float y, float z) { internal.putFloat(x); internal.putFloat(y); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceData.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceData.java index cfd7b5c8f..21eaed753 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceData.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceData.java @@ -4,7 +4,7 @@ import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; public abstract class InstanceData { - protected final Instancer owner; + Instancer owner; boolean dirty; boolean removed; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java index 3233cd7fa..304bac4f0 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java @@ -8,6 +8,7 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nullable; import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.material.MaterialManager; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.client.renderer.ActiveRenderInfo; @@ -55,10 +56,11 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL int cZ = (int) cameraZ; if (tickableInstances.size() > 0) { - for (ITickableInstance instance : tickableInstances.values()) { + tickableInstances.object2ObjectEntrySet().parallelStream().forEach(e -> { + ITickableInstance instance = e.getValue(); if (!instance.decreaseTickRateWithDistance()) { instance.tick(); - continue; + return; } BlockPos pos = instance.getWorldPosition(); @@ -68,7 +70,7 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL int dZ = pos.getZ() - cZ; if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0) instance.tick(); - } + }); } queuedUpdates.forEach(te -> { @@ -94,7 +96,8 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL if (dynamicInstances.size() > 0) { dynamicInstances.object2ObjectEntrySet() - .fastForEach(e -> { + .parallelStream() + .forEach(e -> { IDynamicInstance dyn = e.getValue(); if (!dyn.decreaseFramerateWithDistance() || shouldFrameUpdate(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ)) dyn.beginFrame(); @@ -210,10 +213,14 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL return (frame % getUpdateDivisor(dX, dY, dZ)) == 0; } + // 1 followed by the prime numbers + private static final int[] divisorSequence = new int[] { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 }; protected int getUpdateDivisor(int dX, int dY, int dZ) { int dSq = dX * dX + dY * dY + dZ * dZ; - return (dSq / 1024) + 1; + int i = (dSq / 2048); + + return divisorSequence[Math.min(i, divisorSequence.length - 1)]; } protected void addInternal(T tile) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceMaterial.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceMaterial.java deleted file mode 100644 index ea46a0de4..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceMaterial.java +++ /dev/null @@ -1,176 +0,0 @@ -package com.jozufozu.flywheel.backend.instancing; - -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Arrays; -import java.util.concurrent.ExecutionException; -import java.util.function.Consumer; -import java.util.function.Supplier; - -import org.apache.commons.lang3.tuple.Pair; -import org.lwjgl.opengl.GL11; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.jozufozu.flywheel.backend.RenderWork; -import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; -import com.jozufozu.flywheel.backend.model.BufferedModel; -import com.jozufozu.flywheel.backend.model.IndexedModel; -import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.util.BufferBuilderReader; -import com.jozufozu.flywheel.util.RenderUtil; -import com.jozufozu.flywheel.util.VirtualEmptyModelData; -import com.mojang.blaze3d.matrix.MatrixStack; - -import net.minecraft.block.BlockState; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BlockModelRenderer; -import net.minecraft.client.renderer.BlockRendererDispatcher; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.model.IBakedModel; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.util.Direction; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Vector3i; - -public class InstanceMaterial { - - protected final Supplier originCoordinate; - protected final Cache> models; - protected final MaterialSpec spec; - private final VertexFormat modelFormat; - - public InstanceMaterial(Supplier renderer, MaterialSpec spec) { - this.originCoordinate = renderer; - this.spec = spec; - - this.models = CacheBuilder.newBuilder() - .removalListener(notification -> { - Instancer instancer = (Instancer) notification.getValue(); - RenderWork.enqueue(instancer::delete); - }) - .build(); - modelFormat = this.spec.getModelFormat(); - } - - public boolean nothingToRender() { - return models.size() > 0 && models.asMap() - .values() - .stream() - .allMatch(Instancer::empty); - } - - public void delete() { - models.invalidateAll(); - } - - /** - * Clear all instance data without freeing resources. - */ - public void clear() { - models.asMap() - .values() - .forEach(Instancer::clear); - } - - public void forEachInstancer(Consumer> f) { - for (Instancer model : models.asMap() - .values()) { - f.accept(model); - } - } - - public Instancer getModel(PartialModel partial, BlockState referenceState) { - return get(partial, () -> buildModel(partial.get(), referenceState)); - } - - public Instancer getModel(PartialModel partial, BlockState referenceState, Direction dir) { - return getModel(partial, referenceState, dir, RenderUtil.rotateToFace(dir)); - } - - public Instancer getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier modelTransform) { - return get(Pair.of(dir, partial), () -> buildModel(partial.get(), referenceState, modelTransform.get())); - } - - public Instancer getModel(BlockState toRender) { - return get(toRender, () -> buildModel(toRender)); - } - - public Instancer get(Object key, Supplier supplier) { - try { - return models.get(key, () -> new Instancer<>(supplier.get(), originCoordinate, spec)); - } catch (ExecutionException e) { - e.printStackTrace(); - return null; - } - } - - private BufferedModel buildModel(BlockState renderedState) { - BlockRendererDispatcher dispatcher = Minecraft.getInstance() - .getBlockRenderer(); - return buildModel(dispatcher.getBlockModel(renderedState), renderedState); - } - - private BufferedModel buildModel(IBakedModel model, BlockState renderedState) { - return buildModel(model, renderedState, new MatrixStack()); - } - - private BufferedModel buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) { - BufferBuilderReader reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms)); - - int vertexCount = reader.getVertexCount(); - - ByteBuffer vertices = ByteBuffer.allocate(vertexCount * modelFormat.getStride()); - vertices.order(ByteOrder.nativeOrder()); - - for (int i = 0; i < vertexCount; i++) { - vertices.putFloat(reader.getX(i)); - vertices.putFloat(reader.getY(i)); - vertices.putFloat(reader.getZ(i)); - - vertices.put(reader.getNX(i)); - vertices.put(reader.getNY(i)); - vertices.put(reader.getNZ(i)); - - vertices.putFloat(reader.getU(i)); - vertices.putFloat(reader.getV(i)); - } - - ((Buffer) vertices).rewind(); - - // return new BufferedModel(GlPrimitive.QUADS, format, vertices, vertexCount); - - return IndexedModel.fromSequentialQuads(modelFormat, vertices, vertexCount); - } - - // DOWN, UP, NORTH, SOUTH, WEST, EAST, null - private static final Direction[] dirs; - - static { - Direction[] directions = Direction.values(); - - dirs = Arrays.copyOf(directions, directions.length + 1); - } - - public static BufferBuilder getBufferBuilder(IBakedModel model, BlockState referenceState, MatrixStack ms) { - Minecraft mc = Minecraft.getInstance(); - BlockRendererDispatcher dispatcher = mc.getBlockRenderer(); - BlockModelRenderer blockRenderer = dispatcher.getModelRenderer(); - BufferBuilder builder = new BufferBuilder(512); - - // BakedQuadWrapper quadReader = new BakedQuadWrapper(); - // - // IModelData modelData = model.getModelData(mc.world, BlockPos.ZERO.up(255), referenceState, VirtualEmptyModelData.INSTANCE); - // List quads = Arrays.stream(dirs) - // .flatMap(dir -> model.getQuads(referenceState, dir, mc.world.rand, modelData).stream()) - // .collect(Collectors.toList()); - - builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - blockRenderer.renderModel(mc.level, model, referenceState, BlockPos.ZERO.above(255), ms, builder, true, mc.level.random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE); - builder.end(); - return builder; - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java index 27bcbfacc..95958d162 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -5,6 +5,8 @@ import javax.annotation.Nonnull; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.backend.state.RenderLayer; import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.event.BeginFrameEvent; @@ -28,7 +30,7 @@ import net.minecraftforge.fml.common.Mod; @Mod.EventBusSubscriber(Dist.CLIENT) public class InstancedRenderDispatcher { - private static final WorldAttached> materialManagers = new WorldAttached<>($ -> new MaterialManager<>(Contexts.WORLD)); + private static final WorldAttached> materialManagers = new WorldAttached<>($ -> MaterialManager.builder(Contexts.WORLD).build()); private static final WorldAttached> entityInstanceManager = new WorldAttached<>(world -> new EntityInstanceManager(materialManagers.get(world))); private static final WorldAttached> tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(materialManagers.get(world))); @@ -84,10 +86,14 @@ public class InstancedRenderDispatcher { if (!Backend.getInstance() .canUseInstancing(world)) return; + RenderLayer renderLayer = RenderLayer.fromRenderType(event.type); + + if (renderLayer == null) return; + event.type.setupRenderState(); materialManagers.get(world) - .render(event.type, event.viewProjection, event.camX, event.camY, event.camZ); + .render(renderLayer, event.viewProjection, event.camX, event.camY, event.camZ); event.type.clearRenderState(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java index 76a883bad..23d2821e9 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java @@ -9,6 +9,7 @@ import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance; import com.jozufozu.flywheel.backend.instancing.entity.IEntityInstanceFactory; import com.jozufozu.flywheel.backend.instancing.tile.ITileInstanceFactory; import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; +import com.jozufozu.flywheel.backend.material.MaterialManager; import it.unimi.dsi.fastutil.objects.Object2BooleanLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2BooleanMap; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java index e18c6cefc..babec0d6e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java @@ -11,7 +11,10 @@ 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.backend.material.MaterialSpec; import com.jozufozu.flywheel.backend.model.BufferedModel; +import com.jozufozu.flywheel.core.model.IModel; +import com.jozufozu.flywheel.core.model.ModelUtil; import com.jozufozu.flywheel.util.AttribUtil; import net.minecraft.util.math.vector.Vector3i; @@ -20,7 +23,8 @@ public class Instancer { public final Supplier originCoordinate; - protected final BufferedModel model; + protected final Supplier gen; + protected BufferedModel model; protected final VertexFormat instanceFormat; protected final IInstanceFactory factory; @@ -29,17 +33,46 @@ public class Instancer { protected int glBufferSize = -1; protected int glInstanceCount = 0; private boolean deleted; + private boolean initialized; protected final ArrayList data = new ArrayList<>(); boolean anyToRemove; boolean anyToUpdate; - public Instancer(BufferedModel model, Supplier originCoordinate, MaterialSpec spec) { - this.model = model; + public Instancer(Supplier model, Supplier originCoordinate, MaterialSpec spec) { + this.gen = model; this.factory = spec.getInstanceFactory(); this.instanceFormat = spec.getInstanceFormat(); this.originCoordinate = originCoordinate; + } + + public void render() { + if (!isInitialized()) init(); + if (deleted) return; + + vao.bind(); + renderSetup(); + + if (glInstanceCount > 0) model.drawInstances(glInstanceCount); + + vao.unbind(); + } + + public D createInstance() { + return _add(factory.create(this)); + } + + public void stealInstance(D inOther) { + if (inOther.owner == this) return; + + inOther.owner.anyToRemove = true; + _add(inOther); + } + + private void init() { + model = ModelUtil.getIndexedModel(gen.get()); + initialized = true; if (model.getVertexCount() <= 0) throw new IllegalArgumentException("Refusing to instance a model with no vertices."); @@ -59,27 +92,11 @@ public class Instancer { model.clearState(); } - public void render() { - if (deleted) return; - - vao.bind(); - renderSetup(); - - if (glInstanceCount > 0) model.drawInstances(glInstanceCount); - - vao.unbind(); + public boolean isInitialized() { + return initialized; } - public D createInstance() { - D instanceData = factory.create(this); - instanceData.dirty = true; - anyToUpdate = true; - data.add(instanceData); - - return instanceData; - } - - public boolean empty() { + public boolean isEmpty() { return !anyToUpdate && !anyToRemove && glInstanceCount == 0; } @@ -92,17 +109,31 @@ public class Instancer { } /** - * Free acquired resources. Attempting to use this after calling delete is undefined behavior. + * Free acquired resources. All other Instancer methods are undefined behavior after calling delete. */ public void delete() { if (deleted) return; deleted = true; - model.delete(); + if (isInitialized()) { + model.delete(); - instanceVBO.delete(); - vao.delete(); + instanceVBO.delete(); + vao.delete(); + } + } + + private D _add(D instanceData) { + instanceData.owner = this; + + instanceData.dirty = true; + anyToUpdate = true; + synchronized (data) { + data.add(instanceData); + } + + return instanceData; } protected void renderSetup() { @@ -215,7 +246,7 @@ public class Instancer { final BitSet removeSet = new BitSet(oldSize); for (int i = 0; i < oldSize; i++) { final D element = this.data.get(i); - if (element.removed) { + if (element.removed || element.owner != this) { removeSet.set(i); removeCount++; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialManager.java deleted file mode 100644 index 568c1f21e..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialManager.java +++ /dev/null @@ -1,179 +0,0 @@ -package com.jozufozu.flywheel.backend.instancing; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.core.Materials; -import com.jozufozu.flywheel.core.WorldContext; -import com.jozufozu.flywheel.core.materials.ModelData; -import com.jozufozu.flywheel.core.materials.OrientedData; -import com.jozufozu.flywheel.core.shader.IProgramCallback; -import com.jozufozu.flywheel.core.shader.WorldProgram; -import com.jozufozu.flywheel.util.WeakHashSet; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.inventory.container.PlayerContainer; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.util.math.vector.Vector3i; - -// TODO: 0.2 block atlas should not be a special case -public class MaterialManager

{ - - public static int MAX_ORIGIN_DISTANCE = 100; - - protected final WorldContext

context; - - protected final Map, InstanceMaterial> atlasMaterials; - protected final ArrayList> atlasRenderers; - - protected final Map>> renderers; - protected final Map, InstanceMaterial>> materials; - - protected BlockPos originCoordinate = BlockPos.ZERO; - - private final WeakHashSet listeners; - - public MaterialManager(WorldContext

context) { - this.context = context; - - this.atlasMaterials = new HashMap<>(); - this.atlasRenderers = new ArrayList<>(Backend.getInstance() - .allMaterials() - .size()); - - this.materials = new HashMap<>(); - this.renderers = new HashMap<>(); - - this.listeners = new WeakHashSet<>(); - } - - /** - * Render every model for every material. - * - * @param layer Which vanilla {@link RenderType} is being drawn? - * @param viewProjection How do we get from camera space to clip space? - */ - public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) { - render(layer, viewProjection, camX, camY, camZ, null); - } - - /** - * Render every model for every material. - * - * @param layer Which vanilla {@link RenderType} is being drawn? - * @param viewProjection How do we get from camera space to clip space? - * @param callback Provide additional uniforms or state here. - */ - public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ, IProgramCallback

callback) { - camX -= originCoordinate.getX(); - camY -= originCoordinate.getY(); - camZ -= originCoordinate.getZ(); - - Matrix4f translate = Matrix4f.createTranslateMatrix((float) -camX, (float) -camY, (float) -camZ); - - translate.multiplyBackward(viewProjection); - - for (MaterialRenderer

material : atlasRenderers) { - material.render(layer, translate, camX, camY, camZ, callback); - } - - for (Map.Entry>> entry : renderers.entrySet()) { - Minecraft.getInstance().textureManager.bind(entry.getKey()); - - for (MaterialRenderer

materialRenderer : entry.getValue()) { - materialRenderer.render(layer, translate, camX, camY, camZ, callback); - } - } - } - - public void delete() { - atlasMaterials.values() - .forEach(InstanceMaterial::delete); - materials.values() - .stream() - .flatMap(m -> m.values() - .stream()) - .forEach(InstanceMaterial::delete); - - atlasMaterials.clear(); - atlasRenderers.clear(); - materials.clear(); - renderers.clear(); - } - - @SuppressWarnings("unchecked") - public InstanceMaterial getMaterial(MaterialSpec materialType) { - return (InstanceMaterial) this.atlasMaterials.computeIfAbsent(materialType, type -> { - InstanceMaterial material = new InstanceMaterial<>(this::getOriginCoordinate, type); - - this.atlasRenderers.add(new MaterialRenderer<>(context.getProgramSupplier(type.getProgramName()), material)); - - return material; - }); - } - - @SuppressWarnings("unchecked") - public InstanceMaterial getMaterial(MaterialSpec materialType, ResourceLocation texture) { - return (InstanceMaterial) materials.computeIfAbsent(texture, $ -> new HashMap<>()) - .computeIfAbsent(materialType, type -> { - InstanceMaterial material = new InstanceMaterial<>(this::getOriginCoordinate, type); - - this.renderers.computeIfAbsent(texture, $ -> new ArrayList<>()) - .add(new MaterialRenderer<>(context.getProgramSupplier(type.getProgramName()), material)); - - return material; - }); - } - - public InstanceMaterial getTransformMaterial() { - return getMaterial(Materials.TRANSFORMED); - } - - public InstanceMaterial getOrientedMaterial() { - return getMaterial(Materials.ORIENTED); - } - - public Vector3i getOriginCoordinate() { - return originCoordinate; - } - - public void addListener(OriginShiftListener listener) { - listeners.add(listener); - } - - public void checkAndShiftOrigin(ActiveRenderInfo info) { - int cX = MathHelper.floor(info.getPosition().x); - int cY = MathHelper.floor(info.getPosition().y); - int cZ = MathHelper.floor(info.getPosition().z); - - int dX = cX - originCoordinate.getX(); - int dY = cY - originCoordinate.getY(); - int dZ = cZ - originCoordinate.getZ(); - - if (Math.abs(dX) > MAX_ORIGIN_DISTANCE || Math.abs(dY) > MAX_ORIGIN_DISTANCE || Math.abs(dZ) > MAX_ORIGIN_DISTANCE) { - - originCoordinate = new BlockPos(cX, cY, cZ); - - materials.values() - .stream() - .flatMap(m -> m.values() - .stream()) - .forEach(InstanceMaterial::clear); - atlasMaterials.values() - .forEach(InstanceMaterial::clear); - listeners.forEach(OriginShiftListener::onOriginShift); - } - } - - @FunctionalInterface - public interface OriginShiftListener { - void onOriginShift(); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java index ae4050bac..c3e93fcdb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java @@ -6,9 +6,10 @@ import java.util.stream.Stream; import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; import com.jozufozu.flywheel.backend.instancing.IInstance; import com.jozufozu.flywheel.backend.instancing.ITickableInstance; -import com.jozufozu.flywheel.backend.instancing.InstanceMaterial; -import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; +import com.jozufozu.flywheel.backend.material.InstanceMaterial; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.materials.IFlatLight; import com.jozufozu.flywheel.core.materials.ModelData; import com.jozufozu.flywheel.core.materials.OrientedData; @@ -120,11 +121,11 @@ public abstract class EntityInstance implements IInstance { } protected InstanceMaterial getTransformMaterial() { - return materialManager.getTransformMaterial(); - } + return materialManager.defaultSolid().material(Materials.TRANSFORMED); + } protected InstanceMaterial getOrientedMaterial() { - return materialManager.getOrientedMaterial(); + return materialManager.defaultSolid().material(Materials.ORIENTED); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java index 98429f8d5..7d2da71aa 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java @@ -4,7 +4,7 @@ import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.IInstance; import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; -import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.material.MaterialManager; import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/IEntityInstanceFactory.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/IEntityInstanceFactory.java index 7915947e4..d199fb2a8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/IEntityInstanceFactory.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/IEntityInstanceFactory.java @@ -1,6 +1,6 @@ package com.jozufozu.flywheel.backend.instancing.entity; -import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.material.MaterialManager; import net.minecraft.entity.Entity; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/package-info.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/package-info.java new file mode 100644 index 000000000..2210f8d14 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.jozufozu.flywheel.backend.instancing; + +import javax.annotation.ParametersAreNonnullByDefault; + +import mcp.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/ITileInstanceFactory.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/ITileInstanceFactory.java index b46187ab6..11de652ca 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/ITileInstanceFactory.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/ITileInstanceFactory.java @@ -1,6 +1,6 @@ package com.jozufozu.flywheel.backend.instancing.tile; -import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.material.MaterialManager; import net.minecraft.tileentity.TileEntity; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileEntityInstance.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileEntityInstance.java index 038d571ff..6c7f5bb77 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileEntityInstance.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileEntityInstance.java @@ -6,8 +6,9 @@ import java.util.stream.Stream; import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; import com.jozufozu.flywheel.backend.instancing.IInstance; import com.jozufozu.flywheel.backend.instancing.ITickableInstance; -import com.jozufozu.flywheel.backend.instancing.InstanceMaterial; -import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.material.InstanceMaterial; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.materials.IFlatLight; import com.jozufozu.flywheel.core.materials.ModelData; import com.jozufozu.flywheel.core.materials.OrientedData; @@ -122,10 +123,10 @@ public abstract class TileEntityInstance implements IInsta } protected InstanceMaterial getTransformMaterial() { - return materialManager.getTransformMaterial(); - } + return materialManager.defaultCutout().material(Materials.TRANSFORMED); + } protected InstanceMaterial getOrientedMaterial() { - return materialManager.getOrientedMaterial(); + return materialManager.defaultCutout().material(Materials.ORIENTED); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java index c9dc7dd5f..b8878e019 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java @@ -4,7 +4,7 @@ import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.IInstance; import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; -import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.material.MaterialManager; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/InstanceMaterial.java b/src/main/java/com/jozufozu/flywheel/backend/material/InstanceMaterial.java new file mode 100644 index 000000000..2f55c4c9a --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/material/InstanceMaterial.java @@ -0,0 +1,114 @@ +package com.jozufozu.flywheel.backend.material; + +import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import org.apache.commons.lang3.tuple.Pair; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.jozufozu.flywheel.backend.RenderWork; +import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.model.BlockModel; +import com.jozufozu.flywheel.core.model.IModel; +import com.jozufozu.flywheel.util.RenderUtil; +import com.mojang.blaze3d.matrix.MatrixStack; + +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.util.Direction; +import net.minecraft.util.math.vector.Vector3i; + +public class InstanceMaterial { + + protected final Supplier originCoordinate; + protected final Cache> models; + protected final MaterialSpec spec; + private final VertexFormat modelFormat; + + public InstanceMaterial(Supplier renderer, MaterialSpec spec) { + this.originCoordinate = renderer; + this.spec = spec; + + this.models = CacheBuilder.newBuilder() + .removalListener(notification -> { + Instancer instancer = (Instancer) notification.getValue(); + RenderWork.enqueue(instancer::delete); + }) + .build(); + modelFormat = this.spec.getModelFormat(); + } + + public boolean nothingToRender() { + return models.size() > 0 && models.asMap() + .values() + .stream() + .allMatch(Instancer::isEmpty); + } + + public void delete() { + models.invalidateAll(); + } + + /** + * Clear all instance data without freeing resources. + */ + public void clear() { + models.asMap() + .values() + .forEach(Instancer::clear); + } + + public void forEachInstancer(Consumer> f) { + for (Instancer model : models.asMap() + .values()) { + f.accept(model); + } + } + + public Instancer getModel(PartialModel partial, BlockState referenceState) { + return model(partial, () -> buildModel(partial.get(), referenceState)); + } + + public Instancer getModel(PartialModel partial, BlockState referenceState, Direction dir) { + return getModel(partial, referenceState, dir, RenderUtil.rotateToFace(dir)); + } + + public Instancer getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier modelTransform) { + return model(Pair.of(dir, partial), () -> buildModel(partial.get(), referenceState, modelTransform.get())); + } + + public Instancer getModel(BlockState toRender) { + return model(toRender, () -> buildModel(toRender)); + } + + public Instancer model(Object key, Supplier supplier) { + try { + return models.get(key, () -> new Instancer<>(supplier, originCoordinate, spec)); + } catch (ExecutionException e) { + e.printStackTrace(); + return null; + } + } + + private IModel buildModel(BlockState renderedState) { + BlockRendererDispatcher dispatcher = Minecraft.getInstance() + .getBlockRenderer(); + return buildModel(dispatcher.getBlockModel(renderedState), renderedState); + } + + private IModel buildModel(IBakedModel model, BlockState renderedState) { + return buildModel(model, renderedState, new MatrixStack()); + } + + private IModel buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) { + + return new BlockModel(modelFormat, model, referenceState, ms); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialGroup.java b/src/main/java/com/jozufozu/flywheel/backend/material/MaterialGroup.java new file mode 100644 index 000000000..d9d84e5af --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/material/MaterialGroup.java @@ -0,0 +1,61 @@ +package com.jozufozu.flywheel.backend.material; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.state.IRenderState; +import com.jozufozu.flywheel.core.shader.WorldProgram; + +import net.minecraft.util.math.vector.Matrix4f; + +public class MaterialGroup

{ + + protected final MaterialManager

owner; + protected final IRenderState state; + + private final ArrayList> renderers = new ArrayList<>(); + + private final Map, InstanceMaterial> materials = new HashMap<>(); + + public MaterialGroup(MaterialManager

owner, IRenderState state) { + this.owner = owner; + this.state = state; + } + + public void render(Matrix4f viewProjection, double camX, double camY, double camZ) { + for (MaterialRenderer

renderer : renderers) { + renderer.render(viewProjection, camX, camY, camZ); + } + } + + public void setup(P program) { + + } + + @SuppressWarnings("unchecked") + public InstanceMaterial material(MaterialSpec spec) { + return (InstanceMaterial) 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); + } + + public void delete() { + materials.values() + .forEach(InstanceMaterial::delete); + + materials.clear(); + renderers.clear(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialManager.java b/src/main/java/com/jozufozu/flywheel/backend/material/MaterialManager.java new file mode 100644 index 000000000..d9436c117 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/material/MaterialManager.java @@ -0,0 +1,216 @@ +package com.jozufozu.flywheel.backend.material; + +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.state.IRenderState; +import com.jozufozu.flywheel.backend.state.RenderLayer; +import com.jozufozu.flywheel.backend.state.TextureRenderState; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.WorldContext; +import com.jozufozu.flywheel.core.materials.ModelData; +import com.jozufozu.flywheel.core.materials.OrientedData; +import com.jozufozu.flywheel.core.shader.WorldProgram; +import com.jozufozu.flywheel.util.WeakHashSet; + +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.inventory.container.PlayerContainer; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.util.math.vector.Vector3i; + +public class MaterialManager

{ + + public static int MAX_ORIGIN_DISTANCE = 100; + + protected BlockPos originCoordinate = BlockPos.ZERO; + + protected final WorldContext

context; + protected final GroupFactory

groupFactory; + protected final boolean ignoreOriginCoordinate; + + protected final Map>> layers; + + private final WeakHashSet listeners; + + public MaterialManager(WorldContext

context) { + this(context, MaterialGroup::new, false); + } + + public static

Builder

builder(WorldContext

context) { + return new Builder<>(context); + } + + public MaterialManager(WorldContext

context, GroupFactory

groupFactory, boolean ignoreOriginCoordinate) { + this.context = context; + this.ignoreOriginCoordinate = ignoreOriginCoordinate; + + this.listeners = new WeakHashSet<>(); + this.groupFactory = groupFactory; + + this.layers = new EnumMap<>(RenderLayer.class); + for (RenderLayer value : RenderLayer.values()) { + layers.put(value, new HashMap<>()); + } + } + + /** + * Render every model for every material. + * @param layer Which vanilla {@link RenderType} 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) { + if (!ignoreOriginCoordinate) { + camX -= originCoordinate.getX(); + camY -= originCoordinate.getY(); + camZ -= originCoordinate.getZ(); + + Matrix4f translate = Matrix4f.createTranslateMatrix((float) -camX, (float) -camY, (float) -camZ); + + translate.multiplyBackward(viewProjection); + + viewProjection = translate; + } + + for (Map.Entry> entry : layers.get(layer).entrySet()) { + IRenderState state = entry.getKey(); + MaterialGroup

group = entry.getValue(); + + state.bind(); + group.render(viewProjection, camX, camY, camZ); + state.unbind(); + } + } + + public void delete() { + for (Map> groups : layers.values()) { + + groups.values().forEach(MaterialGroup::delete); + } + } + + 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); + } + + @Deprecated + public InstanceMaterial getMaterial(MaterialSpec materialType, ResourceLocation texture) { + return cutout(TextureRenderState.get(texture)).material(materialType); + } + + @Deprecated + public InstanceMaterial getTransformMaterial() { + return defaultCutout().material(Materials.TRANSFORMED); + } + + @Deprecated + public InstanceMaterial getOrientedMaterial() { + return defaultCutout().material(Materials.ORIENTED); + } + + public Supplier

getProgram(ResourceLocation name) { + return context.getProgramSupplier(name); + } + + public Vector3i getOriginCoordinate() { + return originCoordinate; + } + + public void addListener(OriginShiftListener listener) { + listeners.add(listener); + } + + public void checkAndShiftOrigin(ActiveRenderInfo info) { + int cX = MathHelper.floor(info.getPosition().x); + int cY = MathHelper.floor(info.getPosition().y); + int cZ = MathHelper.floor(info.getPosition().z); + + int dX = cX - originCoordinate.getX(); + int dY = cY - originCoordinate.getY(); + int dZ = cZ - originCoordinate.getZ(); + + if (Math.abs(dX) > MAX_ORIGIN_DISTANCE || Math.abs(dY) > MAX_ORIGIN_DISTANCE || Math.abs(dZ) > MAX_ORIGIN_DISTANCE) { + + originCoordinate = new BlockPos(cX, cY, cZ); + + for (Map> groups : layers.values()) { + groups.values().forEach(MaterialGroup::clear); + } + + listeners.forEach(OriginShiftListener::onOriginShift); + } + } + + private MaterialGroup

createGroup(IRenderState state) { + return groupFactory.create(this, state); + } + + @FunctionalInterface + public interface OriginShiftListener { + void onOriginShift(); + } + + @FunctionalInterface + public interface GroupFactory

{ + MaterialGroup

create(MaterialManager

materialManager, IRenderState state); + } + + public static class Builder

{ + protected final WorldContext

context; + protected GroupFactory

groupFactory = MaterialGroup::new; + protected boolean ignoreOriginCoordinate; + + public Builder(WorldContext

context) { + this.context = context; + } + + public Builder

setGroupFactory(GroupFactory

groupFactory) { + this.groupFactory = groupFactory; + return this; + } + + public Builder

setIgnoreOriginCoordinate(boolean ignoreOriginCoordinate) { + this.ignoreOriginCoordinate = ignoreOriginCoordinate; + return this; + } + + public MaterialManager

build() { + return new MaterialManager<>(context, groupFactory, ignoreOriginCoordinate); + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialRenderer.java b/src/main/java/com/jozufozu/flywheel/backend/material/MaterialRenderer.java similarity index 51% rename from src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialRenderer.java rename to src/main/java/com/jozufozu/flywheel/backend/material/MaterialRenderer.java index ee04fb373..bf4c54b0b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialRenderer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/material/MaterialRenderer.java @@ -1,26 +1,27 @@ -package com.jozufozu.flywheel.backend.instancing; +package com.jozufozu.flywheel.backend.material; +import java.util.function.Consumer; import java.util.function.Supplier; -import com.jozufozu.flywheel.core.shader.IProgramCallback; +import com.jozufozu.flywheel.backend.instancing.Instancer; import com.jozufozu.flywheel.core.shader.WorldProgram; -import net.minecraft.client.renderer.RenderType; import net.minecraft.util.math.vector.Matrix4f; public class MaterialRenderer

{ - private final Supplier

program; - private final InstanceMaterial material; + protected final Supplier

program; + protected final InstanceMaterial material; - public MaterialRenderer(Supplier

programSupplier, InstanceMaterial material) { + protected final Consumer

setupFunc; + + public MaterialRenderer(Supplier

programSupplier, InstanceMaterial material, Consumer

setupFunc) { this.program = programSupplier; this.material = material; + this.setupFunc = setupFunc; } - public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ, IProgramCallback

setup) { - if (!(layer == RenderType.cutoutMipped())) return; - + public void render(Matrix4f viewProjection, double camX, double camY, double camZ) { if (material.nothingToRender()) return; P program = this.program.get(); @@ -29,12 +30,9 @@ public class MaterialRenderer

{ program.uploadViewProjection(viewProjection); program.uploadCameraPos(camX, camY, camZ); - if (setup != null) setup.call(program); + setupFunc.accept(program); - makeRenderCalls(); - } - - protected void makeRenderCalls() { material.forEachInstancer(Instancer::render); } + } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialSpec.java b/src/main/java/com/jozufozu/flywheel/backend/material/MaterialSpec.java similarity index 89% rename from src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialSpec.java rename to src/main/java/com/jozufozu/flywheel/backend/material/MaterialSpec.java index f22f911db..8946fcbff 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialSpec.java +++ b/src/main/java/com/jozufozu/flywheel/backend/material/MaterialSpec.java @@ -1,6 +1,8 @@ -package com.jozufozu.flywheel.backend.instancing; +package com.jozufozu.flywheel.backend.material; 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; diff --git a/src/main/java/com/jozufozu/flywheel/backend/state/IRenderState.java b/src/main/java/com/jozufozu/flywheel/backend/state/IRenderState.java new file mode 100644 index 000000000..f312ab881 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/state/IRenderState.java @@ -0,0 +1,19 @@ +package com.jozufozu.flywheel.backend.state; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.backend.gl.GlTextureUnit; + +import net.minecraft.util.ResourceLocation; + +public interface IRenderState { + + void bind(); + + void unbind(); + + @Nullable + default ResourceLocation getTexture(GlTextureUnit textureUnit) { + return null; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/state/NoCullRenderState.java b/src/main/java/com/jozufozu/flywheel/backend/state/NoCullRenderState.java new file mode 100644 index 000000000..dc5f6ff10 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/state/NoCullRenderState.java @@ -0,0 +1,20 @@ +package com.jozufozu.flywheel.backend.state; + +import com.mojang.blaze3d.platform.GlStateManager; + +public class NoCullRenderState implements IRenderState { + + public static final NoCullRenderState INSTANCE = new NoCullRenderState(); + + protected NoCullRenderState() { } + + @Override + public void bind() { + GlStateManager._disableCull(); + } + + @Override + public void unbind() { + GlStateManager._enableCull(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/state/RenderLayer.java b/src/main/java/com/jozufozu/flywheel/backend/state/RenderLayer.java new file mode 100644 index 000000000..231e5cead --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/state/RenderLayer.java @@ -0,0 +1,25 @@ +package com.jozufozu.flywheel.backend.state; + +import javax.annotation.Nullable; + +import net.minecraft.client.renderer.RenderType; + +public enum RenderLayer { + SOLID, + CUTOUT, + TRANSPARENT, + ; + + @Nullable + public static RenderLayer fromRenderType(RenderType type) { + if (type == RenderType.solid()) { + return SOLID; + } else if (type == RenderType.cutoutMipped()) { + return CUTOUT; + } else if (type == RenderType.translucent()) { + return TRANSPARENT; + } + + return null; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/state/RenderState.java b/src/main/java/com/jozufozu/flywheel/backend/state/RenderState.java new file mode 100644 index 000000000..c72f61643 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/state/RenderState.java @@ -0,0 +1,81 @@ +package com.jozufozu.flywheel.backend.state; + +import java.util.EnumMap; +import java.util.Map; +import java.util.Objects; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.backend.gl.GlTextureUnit; + +import net.minecraft.util.ResourceLocation; + +public class RenderState implements IRenderState { + + private final Map textures; + private final ImmutableList states; + + public RenderState(Map textures, ImmutableList states) { + this.textures = textures; + this.states = states; + } + + @Override + public void bind() { + states.forEach(IRenderState::bind); + } + + @Override + public void unbind() { + states.forEach(IRenderState::unbind); + } + + @Nullable + @Override + public ResourceLocation getTexture(GlTextureUnit textureUnit) { + return textures.get(textureUnit); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RenderState that = (RenderState) o; + return states.equals(that.states); + } + + @Override + public int hashCode() { + return Objects.hash(states); + } + + public static StateBuilder builder() { + return new StateBuilder(); + } + + public static class StateBuilder { + private final ImmutableList.Builder states = ImmutableList.builder(); + private final Map textures = new EnumMap<>(GlTextureUnit.class); + + public StateBuilder texture(ResourceLocation name) { + return addState(TextureRenderState.get(name)); + } + + public StateBuilder addState(IRenderState state) { + if (state instanceof TextureRenderState) { + TextureRenderState tex = (TextureRenderState) state; + if (textures.put(tex.unit, tex.location) == null) { + states.add(state); + } + } else { + states.add(state); + } + return this; + } + + public RenderState build() { + return new RenderState(textures, states.build()); + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/state/TextureRenderState.java b/src/main/java/com/jozufozu/flywheel/backend/state/TextureRenderState.java new file mode 100644 index 000000000..7c34ea096 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/state/TextureRenderState.java @@ -0,0 +1,64 @@ +package com.jozufozu.flywheel.backend.state; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.backend.gl.GlTextureUnit; +import com.jozufozu.flywheel.util.Pair; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.ResourceLocation; + +public class TextureRenderState implements IRenderState { + private static final Map, TextureRenderState> states = new HashMap<>(); + + public final GlTextureUnit unit; + public final ResourceLocation location; + + private TextureRenderState(GlTextureUnit unit, ResourceLocation location) { + this.unit = unit; + this.location = location; + } + + public static TextureRenderState get(ResourceLocation texture) { + return get(GlTextureUnit.T0, texture); + } + + public static TextureRenderState get(GlTextureUnit unit, ResourceLocation texture) { + return states.computeIfAbsent(Pair.of(unit, texture), p -> new TextureRenderState(p.getFirst(), p.getSecond())); + } + + @Override + public void bind() { + unit.makeActive(); + Minecraft.getInstance().textureManager.bind(location); + } + + @Override + public void unbind() { + + } + + @Nullable + @Override + public ResourceLocation getTexture(GlTextureUnit textureUnit) { + if (textureUnit == unit) return location; + return null; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TextureRenderState that = (TextureRenderState) o; + return location.equals(that.location); + } + + @Override + public int hashCode() { + return Objects.hash(location); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/config/BooleanConfig.java b/src/main/java/com/jozufozu/flywheel/config/BooleanConfig.java index 1c3874c7a..8d143dea9 100644 --- a/src/main/java/com/jozufozu/flywheel/config/BooleanConfig.java +++ b/src/main/java/com/jozufozu/flywheel/config/BooleanConfig.java @@ -36,20 +36,20 @@ public enum BooleanConfig { if (player == null || state == null) return; if (state == BooleanDirective.DISPLAY) { - ITextComponent text = new StringTextComponent("Flywheel Renderer is currently: ").append(boolToText(FlwConfig.get().client.enabled.get())); + ITextComponent text = new StringTextComponent("Flywheel renderer is currently: ").append(boolToText(FlwConfig.get().client.enabled.get())); player.displayClientMessage(text, false); return; } boolean enabled = state.get(); - boolean cannotUseER = OptifineHandler.usingShaders() && enabled; + boolean cannotUse = OptifineHandler.usingShaders() && enabled; FlwConfig.get().client.enabled.set(enabled); - ITextComponent text = boolToText(FlwConfig.get().client.enabled.get()).append(new StringTextComponent(" Flywheel Renderer").withStyle(TextFormatting.WHITE)); - ITextComponent error = new StringTextComponent("Flywheel Renderer does not support Optifine Shaders").withStyle(TextFormatting.RED); + ITextComponent text = boolToText(FlwConfig.get().client.enabled.get()).append(new StringTextComponent(" Flywheel renderer").withStyle(TextFormatting.WHITE)); + ITextComponent error = new StringTextComponent("Flywheel renderer does not support Optifine Shaders").withStyle(TextFormatting.RED); - player.displayClientMessage(cannotUseER ? error : text, false); + player.displayClientMessage(cannotUse ? error : text, false); Backend.reloadWorldRenderers(); } @@ -59,14 +59,14 @@ public enum BooleanConfig { if (player == null || state == null) return; if (state == BooleanDirective.DISPLAY) { - ITextComponent text = new StringTextComponent("Normal overlay is currently: ").append(boolToText(FlwConfig.get().client.normalDebug.get())); + ITextComponent text = new StringTextComponent("Normal debug mode is currently: ").append(boolToText(FlwConfig.get().client.debugNormals.get())); player.displayClientMessage(text, false); return; } - FlwConfig.get().client.normalDebug.set(state.get()); + FlwConfig.get().client.debugNormals.set(state.get()); - ITextComponent text = boolToText(FlwConfig.get().client.normalDebug.get()).append(new StringTextComponent(" Normal Overlay").withStyle(TextFormatting.WHITE)); + ITextComponent text = boolToText(FlwConfig.get().client.debugNormals.get()).append(new StringTextComponent(" normal debug mode").withStyle(TextFormatting.WHITE)); player.displayClientMessage(text, false); } diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java b/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java index f107683a3..fe58438d0 100644 --- a/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java +++ b/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java @@ -16,6 +16,6 @@ public class FlwCommands { dispatcher.register(Commands.literal("flywheel") .then(new BooleanConfigCommand("backend", BooleanConfig.ENGINE).register()) - .then(new BooleanConfigCommand("normalOverlay", BooleanConfig.NORMAL_OVERLAY).register())); + .then(new BooleanConfigCommand("debugNormals", BooleanConfig.NORMAL_OVERLAY).register())); } } diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java index bbe66e344..0fd5a2673 100644 --- a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java +++ b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java @@ -30,8 +30,8 @@ public class FlwConfig { return client.enabled.get(); } - public boolean normalOverlayEnabled() { - return client.normalDebug.get(); + public boolean debugNormals() { + return client.debugNormals.get(); } public static void init() { @@ -39,15 +39,15 @@ public class FlwConfig { public static class ClientConfig { public final BooleanValue enabled; - public final BooleanValue normalDebug; + public final BooleanValue debugNormals; public ClientConfig(ForgeConfigSpec.Builder builder) { enabled = builder.comment("Enable or disable the entire engine") .define("enabled", true); - normalDebug = builder.comment("Enable or disable a debug overlay that colors pixels by their normal") - .define("normalDebug", false); + debugNormals = builder.comment("Enable or disable a debug overlay that colors pixels by their normal") + .define("debugNormals", false); } } } diff --git a/src/main/java/com/jozufozu/flywheel/core/Materials.java b/src/main/java/com/jozufozu/flywheel/core/Materials.java index 4ef644926..473d9204d 100644 --- a/src/main/java/com/jozufozu/flywheel/core/Materials.java +++ b/src/main/java/com/jozufozu/flywheel/core/Materials.java @@ -1,6 +1,6 @@ package com.jozufozu.flywheel.core; -import com.jozufozu.flywheel.backend.instancing.MaterialSpec; +import com.jozufozu.flywheel.backend.material.MaterialSpec; import com.jozufozu.flywheel.core.materials.ModelData; import com.jozufozu.flywheel.core.materials.OrientedData; import com.jozufozu.flywheel.event.GatherContextEvent; diff --git a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java index 6336e7049..895208703 100644 --- a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java +++ b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java @@ -14,13 +14,13 @@ import com.jozufozu.flywheel.backend.ResourceUtil; import com.jozufozu.flywheel.backend.ShaderContext; import com.jozufozu.flywheel.backend.ShaderSources; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; -import com.jozufozu.flywheel.backend.instancing.MaterialSpec; import com.jozufozu.flywheel.backend.loading.InstancedArraysTemplate; import com.jozufozu.flywheel.backend.loading.Program; import com.jozufozu.flywheel.backend.loading.ProgramTemplate; import com.jozufozu.flywheel.backend.loading.Shader; import com.jozufozu.flywheel.backend.loading.ShaderLoadingException; import com.jozufozu.flywheel.backend.loading.ShaderTransformer; +import com.jozufozu.flywheel.backend.material.MaterialSpec; import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram; import com.jozufozu.flywheel.core.shader.GameStateProgram; import com.jozufozu.flywheel.core.shader.WorldProgram; diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingGroup.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingGroup.java new file mode 100644 index 000000000..81159c784 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingGroup.java @@ -0,0 +1,36 @@ +package com.jozufozu.flywheel.core.crumbling; + +import com.jozufozu.flywheel.backend.gl.GlTextureUnit; +import com.jozufozu.flywheel.backend.material.MaterialGroup; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.backend.state.IRenderState; +import com.jozufozu.flywheel.core.atlas.AtlasInfo; +import com.jozufozu.flywheel.core.atlas.SheetData; + +import net.minecraft.util.ResourceLocation; + +public class CrumblingGroup

extends MaterialGroup

{ + + private final int width; + private final int height; + + public CrumblingGroup(MaterialManager

owner, IRenderState state) { + super(owner, state); + + ResourceLocation texture = state.getTexture(GlTextureUnit.T0); + + if (texture != null) { + SheetData atlasData = AtlasInfo.getAtlasData(texture); + + width = atlasData.width; + height = atlasData.height; + } else { + width = height = 256; + } + } + + @Override + public void setup(P p) { + p.setAtlasSize(width, height); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java index 3e3446a88..27447a0fe 100644 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java @@ -1,7 +1,7 @@ package com.jozufozu.flywheel.core.crumbling; -import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; +import com.jozufozu.flywheel.backend.material.MaterialManager; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingMaterialManager.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingMaterialManager.java deleted file mode 100644 index b85640569..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingMaterialManager.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.jozufozu.flywheel.core.crumbling; - -import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; -import static org.lwjgl.opengl.GL11.glBindTexture; -import static org.lwjgl.opengl.GL13.GL_TEXTURE0; -import static org.lwjgl.opengl.GL13.glActiveTexture; - -import java.util.ArrayList; -import java.util.Map; - -import com.jozufozu.flywheel.backend.instancing.MaterialManager; -import com.jozufozu.flywheel.backend.instancing.MaterialRenderer; -import com.jozufozu.flywheel.core.WorldContext; -import com.jozufozu.flywheel.core.atlas.AtlasInfo; -import com.jozufozu.flywheel.core.atlas.SheetData; -import com.jozufozu.flywheel.core.shader.IProgramCallback; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.texture.TextureManager; -import net.minecraft.inventory.container.PlayerContainer; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Matrix4f; - -public class CrumblingMaterialManager extends MaterialManager { - - public CrumblingMaterialManager(WorldContext context) { - super(context); - } - - /** - * Render every model for every material. - * - * @param layer Which vanilla {@link RenderType} is being drawn? - * @param viewProjection How do we get from camera space to clip space? - * @param callback Provide additional uniforms or state here. - */ - public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ, IProgramCallback callback) { - camX -= originCoordinate.getX(); - camY -= originCoordinate.getY(); - camZ -= originCoordinate.getZ(); - - Matrix4f translate = Matrix4f.createTranslateMatrix((float) -camX, (float) -camY, (float) -camZ); - - translate.multiplyBackward(viewProjection); - - TextureManager textureManager = Minecraft.getInstance().textureManager; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, textureManager.getTexture(PlayerContainer.BLOCK_ATLAS) - .getId()); - - for (MaterialRenderer material : atlasRenderers) { - material.render(layer, translate, camX, camY, camZ, CrumblingProgram::setDefaultAtlasSize); - } - - for (Map.Entry>> entry : renderers.entrySet()) { - glBindTexture(GL_TEXTURE_2D, textureManager.getTexture(entry.getKey()) - .getId()); - SheetData atlasData = AtlasInfo.getAtlasData(entry.getKey()); - for (MaterialRenderer materialRenderer : entry.getValue()) { - materialRenderer.render(layer, translate, camX, camY, camZ, p -> p.setAtlasSize(atlasData.width, atlasData.height)); - } - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java index b7d53d891..58278ddb9 100644 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java @@ -6,7 +6,6 @@ import java.util.List; import com.jozufozu.flywheel.backend.loading.Program; import com.jozufozu.flywheel.core.atlas.AtlasInfo; -import com.jozufozu.flywheel.core.atlas.SheetData; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.shader.extension.IProgramExtension; @@ -35,16 +34,6 @@ public class CrumblingProgram extends WorldProgram { glUniform2f(uTextureScale, x, y); } - public void setDefaultAtlasSize() { - SheetData atlasData = AtlasInfo.getAtlasData(PlayerContainer.BLOCK_ATLAS); - if (atlasData == null) return; - - int width = atlasData.width; - int height = atlasData.height; - - setAtlasSize(width, height); - } - public void setAtlasSize(int width, int height) { AtlasTexture blockAtlas = AtlasInfo.getAtlas(PlayerContainer.BLOCK_ATLAS); if (blockAtlas == null) return; 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 75ee052dd..caca38784 100644 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java @@ -2,17 +2,16 @@ package com.jozufozu.flywheel.core.crumbling; import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; import static org.lwjgl.opengl.GL11.glBindTexture; -import static org.lwjgl.opengl.GL13.GL_TEXTURE0; -import static org.lwjgl.opengl.GL13.GL_TEXTURE4; -import static org.lwjgl.opengl.GL13.glActiveTexture; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.gl.GlTextureUnit; import com.jozufozu.flywheel.backend.instancing.InstanceManager; -import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.backend.state.RenderLayer; import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.event.ReloadRenderersEvent; import com.jozufozu.flywheel.util.Lazy; @@ -84,9 +83,9 @@ public class CrumblingRenderer { renderer.beginFrame(info); - glActiveTexture(GL_TEXTURE4); + GlTextureUnit.T4.makeActive(); glBindTexture(GL_TEXTURE_2D, breaking.getId()); - materials.render(RenderType.cutoutMipped(), viewProjection, cameraX, cameraY, cameraZ); + materials.render(RenderLayer.SOLID, viewProjection, cameraX, cameraY, cameraZ); renderer.invalidate(); } @@ -95,7 +94,7 @@ public class CrumblingRenderer { crumblingLayer.clearRenderState(); - glActiveTexture(GL_TEXTURE0); + GlTextureUnit.T0.makeActive(); Texture breaking = textureManager.getTexture(ModelBakery.BREAKING_LOCATIONS.get(0)); if (breaking != null) glBindTexture(GL_TEXTURE_2D, breaking.getId()); } @@ -146,7 +145,9 @@ public class CrumblingRenderer { private final InstanceManager instanceManager; private State() { - materialManager = new CrumblingMaterialManager(Contexts.CRUMBLING); + materialManager = MaterialManager.builder(Contexts.CRUMBLING) + .setGroupFactory(CrumblingGroup::new) + .build(); instanceManager = new CrumblingInstanceManager(materialManager); } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java new file mode 100644 index 000000000..3a30847c6 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java @@ -0,0 +1,99 @@ +package com.jozufozu.flywheel.core.model; + +import java.util.Arrays; + +import org.lwjgl.opengl.GL11; + +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; +import com.jozufozu.flywheel.util.BufferBuilderReader; +import com.jozufozu.flywheel.util.VirtualEmptyModelData; +import com.mojang.blaze3d.matrix.MatrixStack; + +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockModelRenderer; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; + +public class BlockModel implements IModel { + private static final MatrixStack IDENTITY = new MatrixStack(); + + private final BufferBuilderReader reader; + + private final VertexFormat modelFormat; + + public BlockModel(VertexFormat modelFormat, IBakedModel model, BlockState referenceState) { + this(modelFormat, model, referenceState, IDENTITY); + } + + public BlockModel(VertexFormat modelFormat, IBakedModel model, BlockState referenceState, MatrixStack ms) { + this.modelFormat = modelFormat; + reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms)); + } + + @Override + public VertexFormat format() { + return modelFormat; + } + + @Override + public int vertexCount() { + return reader.getVertexCount(); + } + + @Override + public void buffer(VecBuffer buffer) { + + int vertexCount = vertexCount(); + + for (int i = 0; i < vertexCount; i++) { + buffer.putVec3(reader.getX(i), reader.getY(i), reader.getZ(i)); + + buffer.putVec3(reader.getNX(i), reader.getNY(i), reader.getNZ(i)); + + buffer.putVec2(reader.getU(i), reader.getV(i)); + } + } + + @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(); + BlockModelRenderer blockRenderer = dispatcher.getModelRenderer(); + BufferBuilder builder = new BufferBuilder(512); + + // BakedQuadWrapper quadReader = new BakedQuadWrapper(); + // + // IModelData modelData = model.getModelData(mc.world, BlockPos.ZERO.up(255), referenceState, VirtualEmptyModelData.INSTANCE); + // List quads = Arrays.stream(dirs) + // .flatMap(dir -> model.getQuads(referenceState, dir, mc.world.rand, modelData).stream()) + // .collect(Collectors.toList()); + + builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); + blockRenderer.renderModel(mc.level, model, referenceState, BlockPos.ZERO.above(255), ms, builder, true, mc.level.random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE); + builder.end(); + return builder; + } + + // DOWN, UP, NORTH, SOUTH, WEST, EAST, null + private static final Direction[] dirs; + + static { + Direction[] directions = Direction.values(); + + dirs = Arrays.copyOf(directions, directions.length + 1); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/model/IModel.java b/src/main/java/com/jozufozu/flywheel/core/model/IModel.java new file mode 100644 index 000000000..4c3e9d027 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/model/IModel.java @@ -0,0 +1,26 @@ +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; + +/** + * A model that can be rendered by flywheel. + */ +public interface IModel { + + /** + * Copy this model into the given buffer. + */ + void buffer(VecBuffer buffer); + + int vertexCount(); + + VertexFormat format(); + + ElementBuffer createEBO(); + + default int size() { + return vertexCount() * format().getStride(); + } +} 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 05ec25cdf..fff356878 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java @@ -1,8 +1,52 @@ package com.jozufozu.flywheel.core.model; -public class ModelPart { +import java.util.List; + +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.Formats; +import com.jozufozu.flywheel.core.QuadConverter; + +public class ModelPart implements IModel { + + private final List cuboids; + private int vertices; + + public ModelPart(List cuboids) { + this.cuboids = cuboids; + + vertices = 0; + + for (PartBuilder.CuboidBuilder cuboid : cuboids) { + vertices += cuboid.vertices(); + } + } public static PartBuilder builder(int sizeU, int sizeV) { return new PartBuilder(sizeU, sizeV); } + + @Override + public void buffer(VecBuffer buffer) { + for (PartBuilder.CuboidBuilder cuboid : cuboids) { + cuboid.buffer(buffer); + } + } + + @Override + public int vertexCount() { + return vertices; + } + + @Override + 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 new file mode 100644 index 000000000..3039e2218 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java @@ -0,0 +1,21 @@ +package com.jozufozu.flywheel.core.model; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; +import com.jozufozu.flywheel.backend.model.IndexedModel; + +public class ModelUtil { + public static IndexedModel getIndexedModel(IModel blockModel) { + ByteBuffer vertices = ByteBuffer.allocate(blockModel.size()); + vertices.order(ByteOrder.nativeOrder()); + + blockModel.buffer(new VecBuffer(vertices)); + + ((Buffer) vertices).rewind(); + + return new IndexedModel(blockModel.format(), vertices, blockModel.vertexCount(), blockModel.createEBO()); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/model/PartBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/PartBuilder.java index 5fe981d58..f7a4bfe8e 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/PartBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/PartBuilder.java @@ -8,9 +8,6 @@ import java.util.List; import java.util.Set; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; -import com.jozufozu.flywheel.backend.model.BufferedModel; -import com.jozufozu.flywheel.backend.model.IndexedModel; -import com.jozufozu.flywheel.core.Formats; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.Direction; @@ -18,23 +15,16 @@ import net.minecraft.util.math.vector.Vector3f; public class PartBuilder { - private float sizeU = 64.0F; - private float sizeV = 32.0F; + private final float sizeU; + private final float sizeV; private TextureAtlasSprite sprite; private final List cuboids = new ArrayList<>(); - public PartBuilder() { } - public PartBuilder(int sizeU, int sizeV) { - this.setTextureSize(sizeU, sizeV); - } - - public PartBuilder setTextureSize(int textureWidth, int textureHeight) { - this.sizeU = (float)textureWidth; - this.sizeV = (float)textureHeight; - return this; + this.sizeU = (float) sizeU; + this.sizeV = (float) sizeV; } public PartBuilder sprite(TextureAtlasSprite sprite) { @@ -46,22 +36,8 @@ public class PartBuilder { return new CuboidBuilder(this); } - public BufferedModel build() { - int vertices = 0; - - for (CuboidBuilder cuboid : cuboids) { - vertices += cuboid.vertices(); - } - - VecBuffer buffer = VecBuffer.allocate(vertices * Formats.UNLIT_MODEL.getStride()); - - for (CuboidBuilder cuboid : cuboids) { - cuboid.buffer(buffer); - } - - buffer.rewind(); - - return IndexedModel.fromSequentialQuads(Formats.UNLIT_MODEL, buffer.unwrap(), vertices); + public ModelPart build() { + return new ModelPart(cuboids); } private PartBuilder addCuboid(CuboidBuilder builder) { @@ -84,6 +60,8 @@ public class PartBuilder { float posY2; float posZ2; + boolean invertYZ; + final PartBuilder partBuilder; CuboidBuilder(PartBuilder partBuilder) { @@ -123,6 +101,14 @@ public class PartBuilder { return this; } + /** + * Pulls the cuboid "inside out" through the Y and Z axes. + */ + public CuboidBuilder invertYZ() { + this.invertYZ = true; + return this; + } + public PartBuilder endCuboid() { return partBuilder.addCuboid(this); } @@ -137,14 +123,21 @@ public class PartBuilder { float sizeY = posY2 - posY1; float sizeZ = posZ2 - posZ1; - Vector3f lll = new Vector3f(posX1 / 16f, posY1 / 16f, posZ1 / 16f); - Vector3f hll = new Vector3f(posX2 / 16f, posY1 / 16f, posZ1 / 16f); - Vector3f hhl = new Vector3f(posX2 / 16f, posY2 / 16f, posZ1 / 16f); - Vector3f lhl = new Vector3f(posX1 / 16f, posY2 / 16f, posZ1 / 16f); - Vector3f llh = new Vector3f(posX1 / 16f, posY1 / 16f, posZ2 / 16f); - Vector3f hlh = new Vector3f(posX2 / 16f, posY1 / 16f, posZ2 / 16f); - Vector3f hhh = new Vector3f(posX2 / 16f, posY2 / 16f, posZ2 / 16f); - Vector3f lhh = new Vector3f(posX1 / 16f, posY2 / 16f, posZ2 / 16f); + float posX1 = this.posX1 / 16f; + float posY1 = this.posY1 / 16f; + float posZ1 = this.posZ1 / 16f; + float posX2 = this.posX2 / 16f; + float posY2 = this.posY2 / 16f; + float posZ2 = this.posZ2 / 16f; + + Vector3f lll = new Vector3f(posX1, posY1, posZ1); + Vector3f hll = new Vector3f(posX2, posY1, posZ1); + Vector3f hhl = new Vector3f(posX2, posY2, posZ1); + Vector3f lhl = new Vector3f(posX1, posY2, posZ1); + Vector3f llh = new Vector3f(posX1, posY1, posZ2); + Vector3f hlh = new Vector3f(posX2, posY1, posZ2); + Vector3f hhh = new Vector3f(posX2, posY2, posZ2); + Vector3f lhh = new Vector3f(posX1, posY2, posZ2); float f4 = getU((float)textureOffsetU); float f5 = getU((float)textureOffsetU + sizeZ); float f6 = getU((float)textureOffsetU + sizeZ + sizeX); @@ -155,12 +148,21 @@ public class PartBuilder { float f11 = getV((float)textureOffsetV + sizeZ); float f12 = getV((float)textureOffsetV + sizeZ + sizeY); - quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, Direction.DOWN); - quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, Direction.UP); - quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, Direction.WEST); - quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, Direction.NORTH); - quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, Direction.EAST); - quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, Direction.SOUTH); + if (invertYZ) { + quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f6, f11, f7, f10, Direction.DOWN); + quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f5, f10, f6, f11, Direction.UP); + quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f5, f12, f4, f11, Direction.WEST); + quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f9, f12, f8, f11, Direction.NORTH); + quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f8, f12, f6, f11, Direction.EAST); + quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f6, f12, f5, f11, Direction.SOUTH); + } else { + quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, Direction.DOWN); + quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, Direction.UP); + quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, Direction.WEST); + quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, Direction.NORTH); + quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, Direction.EAST); + quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, Direction.SOUTH); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/package-info.java b/src/main/java/com/jozufozu/flywheel/core/model/package-info.java new file mode 100644 index 000000000..33950a9c0 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/model/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.jozufozu.flywheel.core.model; + +import javax.annotation.ParametersAreNonnullByDefault; + +import mcp.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/IProgramCallback.java b/src/main/java/com/jozufozu/flywheel/core/shader/IProgramCallback.java deleted file mode 100644 index 4dae733e9..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/shader/IProgramCallback.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.jozufozu.flywheel.core.shader; - -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; - -/** - * Used to define shader uniforms. - */ -@FunctionalInterface -public interface IProgramCallback

{ - - void call(P program); - - default IProgramCallback

andThen(IProgramCallback

other) { - return program -> { - call(program); - other.call(program); - }; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java b/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java index b3a6b9868..60b6589cb 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java @@ -5,7 +5,6 @@ import static org.lwjgl.opengl.GL20.glUniform3f; import java.util.List; -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.loading.Program; import com.jozufozu.flywheel.core.shader.extension.IProgramExtension; import com.jozufozu.flywheel.util.AnimationTickHolder; diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/gamestate/NormalDebugStateProvider.java b/src/main/java/com/jozufozu/flywheel/core/shader/gamestate/NormalDebugStateProvider.java index 3bafd5fb7..60084241a 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/gamestate/NormalDebugStateProvider.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/gamestate/NormalDebugStateProvider.java @@ -18,7 +18,7 @@ public class NormalDebugStateProvider implements IBooleanStateProvider { @Override public boolean isTrue() { return FlwConfig.get() - .normalOverlayEnabled(); + .debugNormals(); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/light/LightVolume.java b/src/main/java/com/jozufozu/flywheel/light/LightVolume.java index f5a70b5b2..4f7bbe130 100644 --- a/src/main/java/com/jozufozu/flywheel/light/LightVolume.java +++ b/src/main/java/com/jozufozu/flywheel/light/LightVolume.java @@ -29,6 +29,7 @@ import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.GlTexture; +import com.jozufozu.flywheel.backend.gl.GlTextureUnit; import com.jozufozu.flywheel.backend.gl.versioned.RGPixelFormat; import net.minecraft.util.math.BlockPos; @@ -257,7 +258,7 @@ public class LightVolume { // just in case something goes wrong or we accidentally call this before this volume is properly disposed of. if (lightData == null || removed) return; - glActiveTexture(GL_TEXTURE4); + GlTextureUnit.T4.makeActive(); glTexture.bind(); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); diff --git a/src/main/java/com/jozufozu/flywheel/mixin/FastChunkProviderMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/FastChunkProviderMixin.java new file mode 100644 index 000000000..9a1f3a0f9 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/FastChunkProviderMixin.java @@ -0,0 +1,68 @@ +package com.jozufozu.flywheel.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.client.multiplayer.ClientChunkProvider; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.network.PacketBuffer; +import net.minecraft.world.biome.BiomeContainer; +import net.minecraft.world.chunk.AbstractChunkProvider; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.ChunkStatus; +import net.minecraft.world.chunk.IChunk; + +@Mixin(ClientChunkProvider.class) +public abstract class FastChunkProviderMixin extends AbstractChunkProvider { + + @Unique + private int lastX; + @Unique + private int lastZ; + + @Unique + private IChunk lastChunk; + + @Inject(method = "getChunk", + 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); + } + } + + @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; + } + } + + @Inject(method = "drop", at = @At("HEAD")) + public void invalidateOnDrop(int x, int z, CallbackInfo ci) { + 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; + } + + @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; + + return clientChunkProvider.hasChunk(x, z); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java index f78584cf8..056efaa7b 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java @@ -9,8 +9,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.OptifineHandler; -import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer; import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.ReloadRenderersEvent; import com.jozufozu.flywheel.event.RenderLayerEvent; diff --git a/src/main/java/com/jozufozu/flywheel/util/Lazy.java b/src/main/java/com/jozufozu/flywheel/util/Lazy.java index 6594a313f..344a07976 100644 --- a/src/main/java/com/jozufozu/flywheel/util/Lazy.java +++ b/src/main/java/com/jozufozu/flywheel/util/Lazy.java @@ -1,7 +1,6 @@ package com.jozufozu.flywheel.util; import java.util.function.Consumer; -import java.util.function.Supplier; import javax.annotation.Nonnull; diff --git a/src/main/java/com/jozufozu/flywheel/util/RenderUtil.java b/src/main/java/com/jozufozu/flywheel/util/RenderUtil.java index 4698835ad..2417604bb 100644 --- a/src/main/java/com/jozufozu/flywheel/util/RenderUtil.java +++ b/src/main/java/com/jozufozu/flywheel/util/RenderUtil.java @@ -10,6 +10,20 @@ import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Vector3f; public class RenderUtil { + + private static final Matrix4f IDENTITY = new Matrix4f(); + static { + IDENTITY.setIdentity(); + } + + public static Matrix4f getIdentity() { + return IDENTITY; + } + + public static Matrix4f copyIdentity() { + return IDENTITY.copy(); + } + public static int nextPowerOf2(int a) { int h = Integer.highestOneBit(a); return (h == a) ? h : (h << 1); diff --git a/src/main/java/com/jozufozu/flywheel/util/transform/MatrixTransformStack.java b/src/main/java/com/jozufozu/flywheel/util/transform/MatrixTransformStack.java index 93867511e..ed08b5dc7 100644 --- a/src/main/java/com/jozufozu/flywheel/util/transform/MatrixTransformStack.java +++ b/src/main/java/com/jozufozu/flywheel/util/transform/MatrixTransformStack.java @@ -6,7 +6,19 @@ import net.minecraft.util.math.vector.Quaternion; public class MatrixTransformStack implements TransformStack { - private final MatrixStack internal = new MatrixStack(); + private final MatrixStack internal; + + public MatrixTransformStack() { + this(new MatrixStack()); + } + + public MatrixTransformStack(MatrixStack internal) { + this.internal = internal; + } + + public static MatrixTransformStack of(MatrixStack ms) { + return new MatrixTransformStack(ms); + } public MatrixStack unwrap() { return internal; @@ -24,13 +36,21 @@ public class MatrixTransformStack implements TransformStack { return this; } + @Override + public TransformStack scale(float factor) { + internal.scale(factor, factor, factor); + return this; + } + @Override public TransformStack push() { + internal.pushPose(); return this; } @Override public TransformStack pop() { + internal.popPose(); return this; } } diff --git a/src/main/java/com/jozufozu/flywheel/util/transform/QuaternionTransformStack.java b/src/main/java/com/jozufozu/flywheel/util/transform/QuaternionTransformStack.java index 364371b72..3e6908201 100644 --- a/src/main/java/com/jozufozu/flywheel/util/transform/QuaternionTransformStack.java +++ b/src/main/java/com/jozufozu/flywheel/util/transform/QuaternionTransformStack.java @@ -41,6 +41,11 @@ public class QuaternionTransformStack implements TransformStack { return this; } + @Override + public TransformStack scale(float factor) { + return this; + } + @Override public TransformStack pop() { diff --git a/src/main/java/com/jozufozu/flywheel/util/transform/TransformStack.java b/src/main/java/com/jozufozu/flywheel/util/transform/TransformStack.java index e5c4addd2..1962bcf26 100644 --- a/src/main/java/com/jozufozu/flywheel/util/transform/TransformStack.java +++ b/src/main/java/com/jozufozu/flywheel/util/transform/TransformStack.java @@ -13,6 +13,8 @@ public interface TransformStack { TransformStack multiply(Quaternion quaternion); + TransformStack scale(float factor); + TransformStack push(); TransformStack pop(); @@ -43,11 +45,27 @@ public interface TransformStack { } default TransformStack centre() { - return translate(CENTER); + return translateAll(0.5); } default TransformStack unCentre() { - return translateBack(CENTER); + return translateAll(-0.5); + } + + default TransformStack translateAll(double v) { + return translate(v, v, v); + } + + default TransformStack translateX(double x) { + return translate(x, 0, 0); + } + + default TransformStack translateY(double y) { + return translate(0, y, 0); + } + + default TransformStack translateZ(double z) { + return translate(0, 0, z); } default TransformStack translate(Vector3i vec) { diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java index 0209fd586..42358f7e1 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java @@ -1,9 +1,8 @@ package com.jozufozu.flywheel.vanilla; import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; -import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; -import com.jozufozu.flywheel.backend.model.BufferedModel; +import com.jozufozu.flywheel.backend.material.MaterialManager; import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.materials.OrientedData; import com.jozufozu.flywheel.core.model.ModelPart; @@ -58,12 +57,13 @@ public class BellInstance extends TileEntityInstance implements } private OrientedData createBellInstance() { - return materialManager.getMaterial(Materials.ORIENTED) - .get(tile.getType(), BellInstance::createBellModel) + return materialManager.defaultCutout() + .material(Materials.ORIENTED) + .model(tile.getType(), BellInstance::createBellModel) .createInstance(); } - private static BufferedModel createBellModel() { + private static ModelPart createBellModel() { return ModelPart.builder(32, 32) .sprite(BellTileEntityRenderer.BELL_RESOURCE_LOCATION.sprite()) .cuboid() diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java index 149e97355..d859d3d5b 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java @@ -5,9 +5,9 @@ import java.util.Calendar; import javax.annotation.Nonnull; import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; -import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; -import com.jozufozu.flywheel.backend.model.BufferedModel; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.backend.state.TextureRenderState; import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.materials.ModelData; import com.jozufozu.flywheel.core.materials.OrientedData; @@ -119,19 +119,21 @@ public class ChestInstance extends TileEntityI private OrientedData baseInstance() { - return materialManager.getMaterial(Materials.ORIENTED, renderMaterial.atlasLocation()) - .get("base_" + renderMaterial.texture(), this::getBaseModel) + return materialManager.solid(TextureRenderState.get(renderMaterial.atlasLocation())) + .material(Materials.ORIENTED) + .model("base_" + renderMaterial.texture(), this::getBaseModel) .createInstance(); } private ModelData lidInstance() { - return materialManager.getMaterial(Materials.TRANSFORMED, renderMaterial.atlasLocation()) - .get("lid_" + renderMaterial.texture(), this::getLidModel) + return materialManager.solid(TextureRenderState.get(renderMaterial.atlasLocation())) + .material(Materials.TRANSFORMED) + .model("lid_" + renderMaterial.texture(), this::getLidModel) .createInstance(); } - private BufferedModel getBaseModel() { + private ModelPart getBaseModel() { switch (chestType) { case LEFT: @@ -164,7 +166,7 @@ public class ChestInstance extends TileEntityI .build(); } - private BufferedModel getLidModel() { + private ModelPart getLidModel() { switch (chestType) { case LEFT: diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/RenderStates.java b/src/main/java/com/jozufozu/flywheel/vanilla/RenderStates.java new file mode 100644 index 000000000..54b6389c9 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/vanilla/RenderStates.java @@ -0,0 +1,14 @@ +package com.jozufozu.flywheel.vanilla; + +import com.jozufozu.flywheel.backend.state.IRenderState; +import com.jozufozu.flywheel.backend.state.NoCullRenderState; +import com.jozufozu.flywheel.backend.state.RenderState; + +import net.minecraft.client.renderer.Atlases; + +public class RenderStates { + public static final IRenderState SHULKER = RenderState.builder() + .texture(Atlases.SHULKER_SHEET) + .addState(NoCullRenderState.INSTANCE) + .build(); +} diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java new file mode 100644 index 000000000..4b01400c1 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java @@ -0,0 +1,131 @@ +package com.jozufozu.flywheel.vanilla; + +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.materials.ModelData; +import com.jozufozu.flywheel.core.model.ModelPart; +import com.jozufozu.flywheel.util.AnimationTickHolder; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; + +import net.minecraft.block.ShulkerBoxBlock; +import net.minecraft.client.renderer.Atlases; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.item.DyeColor; +import net.minecraft.tileentity.ShulkerBoxTileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.math.vector.Quaternion; +import net.minecraft.util.math.vector.Vector3f; + +public class ShulkerBoxInstance extends TileEntityInstance implements IDynamicInstance { + + private final TextureAtlasSprite texture; + + private final ModelData base; + private final ModelData lid; + private final MatrixTransformStack stack; + + private float lastProgress = Float.NaN; + + public ShulkerBoxInstance(MaterialManager materialManager, ShulkerBoxTileEntity tile) { + super(materialManager, tile); + + DyeColor color = tile.getColor(); + if (color == null) { + texture = Atlases.DEFAULT_SHULKER_TEXTURE_LOCATION.sprite(); + } else { + texture = Atlases.SHULKER_TEXTURE_LOCATION.get(color.getId()).sprite(); + } + Quaternion rotation = getDirection().getRotation(); + + stack = new MatrixTransformStack(); + + stack.translate(getInstancePosition()) + .scale(0.9995f) + .translateAll(0.00025) + .centre() + .multiply(rotation) + .unCentre(); + + base = makeBaseInstance().setTransform(stack.unwrap()); + + stack.translateY(0.25); + + lid = makeLidInstance().setTransform(stack.unwrap()); + } + + @Override + public void beginFrame() { + float progress = tile.getProgress(AnimationTickHolder.getPartialTicks()); + + if (progress == lastProgress) return; + lastProgress = progress; + + Quaternion spin = Vector3f.YP.rotationDegrees(270.0F * progress); + + stack.push() + .centre() + .multiply(spin) + .unCentre() + .translateY(progress * 0.5f); + + lid.setTransform(stack.unwrap()); + + stack.pop(); + } + + @Override + public void remove() { + base.delete(); + lid.delete(); + } + + @Override + public void updateLight() { + relight(pos, base, lid); + } + + private ModelData makeBaseInstance() { + return materialManager.cutout(RenderStates.SHULKER) + .material(Materials.TRANSFORMED) + .model("base_" + texture.getName(), this::makeBaseModel) + .createInstance(); + } + + private ModelData makeLidInstance() { + return materialManager.cutout(RenderStates.SHULKER) + .material(Materials.TRANSFORMED) + .model("lid_" + texture.getName(), this::makeLidModel) + .createInstance(); + } + + private ModelPart makeBaseModel() { + return ModelPart.builder(64, 64) + .sprite(texture) + .cuboid() + .textureOffset(0, 28) + .size(16, 8, 16) + .invertYZ() + .endCuboid() + .build(); + } + + private ModelPart makeLidModel() { + return ModelPart.builder(64, 64) + .sprite(texture) + .cuboid() + .size(16, 12, 16) + .invertYZ() + .endCuboid() + .build(); + } + + private Direction getDirection() { + if (blockState.getBlock() instanceof ShulkerBoxBlock) { + return blockState.getValue(ShulkerBoxBlock.FACING); + } + + return Direction.UP; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/VanillaInstances.java b/src/main/java/com/jozufozu/flywheel/vanilla/VanillaInstances.java index 36f6567ee..bd8c84d21 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/VanillaInstances.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/VanillaInstances.java @@ -8,20 +8,19 @@ import net.minecraft.tileentity.TileEntityType; * TODO: * * - * * + * * * + * + * + * * * * * * * - * - * - * - * * *
{@link TileEntityType#SIGN} {@link net.minecraft.client.renderer.tileentity.SignTileEntityRenderer SignTileEntityRenderer}
{@link TileEntityType#MOB_SPAWNER} {@link net.minecraft.client.renderer.tileentity.MobSpawnerTileEntityRenderer MobSpawnerTileEntityRenderer}
{@link TileEntityType#PISTON} {@link net.minecraft.client.renderer.tileentity.PistonTileEntityRenderer PistonTileEntityRenderer}
{@link TileEntityType#CONDUIT} {@link net.minecraft.client.renderer.tileentity.ConduitTileEntityRenderer ConduitTileEntityRenderer}
{@link TileEntityType#ENCHANTING_TABLE} {@link net.minecraft.client.renderer.tileentity.EnchantmentTableTileEntityRenderer EnchantmentTableTileEntityRenderer}
{@link TileEntityType#LECTERN} {@link net.minecraft.client.renderer.tileentity.LecternTileEntityRenderer LecternTileEntityRenderer}
{@link TileEntityType#MOB_SPAWNER} {@link net.minecraft.client.renderer.tileentity.MobSpawnerTileEntityRenderer MobSpawnerTileEntityRenderer}
{@link TileEntityType#BED} {@link net.minecraft.client.renderer.tileentity.BedTileEntityRenderer BedTileEntityRenderer}
^^ Interesting - Major vv
{@link TileEntityType#END_PORTAL} {@link net.minecraft.client.renderer.tileentity.EndPortalTileEntityRenderer EndPortalTileEntityRenderer}
{@link TileEntityType#END_GATEWAY} {@link net.minecraft.client.renderer.tileentity.EndGatewayTileEntityRenderer EndGatewayTileEntityRenderer}
{@link TileEntityType#BEACON} {@link net.minecraft.client.renderer.tileentity.BeaconTileEntityRenderer BeaconTileEntityRenderer}
{@link TileEntityType#SKULL} {@link net.minecraft.client.renderer.tileentity.SkullTileEntityRenderer SkullTileEntityRenderer}
{@link TileEntityType#BANNER} {@link net.minecraft.client.renderer.tileentity.BannerTileEntityRenderer BannerTileEntityRenderer}
{@link TileEntityType#STRUCTURE_BLOCK} {@link net.minecraft.client.renderer.tileentity.StructureTileEntityRenderer StructureTileEntityRenderer}
{@link TileEntityType#SHULKER_BOX} {@link net.minecraft.client.renderer.tileentity.ShulkerBoxTileEntityRenderer ShulkerBoxTileEntityRenderer}
{@link TileEntityType#BED} {@link net.minecraft.client.renderer.tileentity.BedTileEntityRenderer BedTileEntityRenderer}
{@link TileEntityType#CONDUIT} {@link net.minecraft.client.renderer.tileentity.ConduitTileEntityRenderer ConduitTileEntityRenderer}
{@link TileEntityType#BELL} {@link net.minecraft.client.renderer.tileentity.BellTileEntityRenderer BellTileEntityRenderer}
{@link TileEntityType#CAMPFIRE} {@link net.minecraft.client.renderer.tileentity.CampfireTileEntityRenderer CampfireTileEntityRenderer}
*/ @@ -43,5 +42,9 @@ public class VanillaInstances { r.tile(TileEntityType.BELL) .setSkipRender(true) .factory(BellInstance::new); + + r.tile(TileEntityType.SHULKER_BOX) + .setSkipRender(true) + .factory(ShulkerBoxInstance::new); } } diff --git a/src/main/resources/flywheel.mixins.json b/src/main/resources/flywheel.mixins.json index b930f4173..2c4db2153 100644 --- a/src/main/resources/flywheel.mixins.json +++ b/src/main/resources/flywheel.mixins.json @@ -4,7 +4,6 @@ "package": "com.jozufozu.flywheel.mixin", "compatibilityLevel": "JAVA_8", "refmap": "flywheel.refmap.json", - "mixins": [], "client": [ "CancelEntityRenderMixin", "CancelTileEntityRenderMixin", @@ -18,7 +17,8 @@ "atlas.AtlasDataMixin", "atlas.SheetDataAccessor", "light.LightUpdateMixin", - "light.NetworkLightUpdateMixin" + "light.NetworkLightUpdateMixin", + "FastChunkProviderMixin" ], "injectors": { "defaultRequire": 0