diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java b/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java index ede6c9b81..8ceb05d3c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java +++ b/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java @@ -17,7 +17,6 @@ import java.util.function.Predicate; import java.util.stream.Stream; import javax.annotation.Nonnull; -import javax.annotation.ParametersAreNonnullByDefault; import org.lwjgl.system.MemoryUtil; @@ -47,7 +46,6 @@ import net.minecraftforge.resource.IResourceType; import net.minecraftforge.resource.ISelectiveResourceReloadListener; import net.minecraftforge.resource.VanillaResourceType; -@ParametersAreNonnullByDefault public class ShaderSources implements ISelectiveResourceReloadListener { public static final String SHADER_DIR = "flywheel/shaders/"; public static final String PROGRAM_DIR = "flywheel/programs/"; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/CrumblingRenderer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/CrumblingRenderer.java new file mode 100644 index 000000000..bb8e44ce2 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/CrumblingRenderer.java @@ -0,0 +1,130 @@ +package com.jozufozu.flywheel.backend.instancing; + +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.core.Contexts; +import com.jozufozu.flywheel.core.crumbling.CrumblingInstanceManager; +import com.jozufozu.flywheel.core.crumbling.CrumblingMaterialManager; +import com.jozufozu.flywheel.core.crumbling.CrumblingProgram; +import com.jozufozu.flywheel.event.ReloadRenderersEvent; + +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.client.renderer.DestroyBlockProgress; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.model.ModelBakery; +import net.minecraft.client.renderer.texture.Texture; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.LazyValue; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +/** + * Responsible for rendering the block breaking overlay for instanced tiles. + */ +@OnlyIn(Dist.CLIENT) +@Mod.EventBusSubscriber(Dist.CLIENT) +public class CrumblingRenderer { + + private static final LazyValue> materialManager = new LazyValue<>(() -> new CrumblingMaterialManager(Contexts.CRUMBLING)); + private static final LazyValue> manager = new LazyValue<>(() -> new CrumblingInstanceManager(materialManager.getValue())); + + private static final RenderType crumblingLayer = ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(0); + + public static void renderBreaking(ClientWorld world, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) { + if (!Backend.getInstance() + .canUseInstancing(world)) return; + + Int2ObjectMap> activeStages = getActiveStageTiles(world); + + if (activeStages.isEmpty()) return; + + InstanceManager renderer = manager.getValue(); + + TextureManager textureManager = Minecraft.getInstance().textureManager; + ActiveRenderInfo info = Minecraft.getInstance().gameRenderer.getActiveRenderInfo(); + + MaterialManager materials = materialManager.getValue(); + crumblingLayer.startDrawing(); + + for (Int2ObjectMap.Entry> stage : activeStages.int2ObjectEntrySet()) { + int i = stage.getIntKey(); + Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(i)); + + // something about when we call this means that the textures are not ready for use on the first frame they should appear + if (breaking != null) { + stage.getValue().forEach(renderer::add); + + renderer.beginFrame(info); + + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId()); + materials.render(RenderType.getCutoutMipped(), viewProjection, cameraX, cameraY, cameraZ); + + renderer.invalidate(); + } + + } + + crumblingLayer.endDrawing(); + + glActiveTexture(GL_TEXTURE0); + Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(0)); + if (breaking != null) glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId()); + } + + /** + * Associate each breaking stage with a list of all tile entities at that stage. + */ + private static Int2ObjectMap> getActiveStageTiles(ClientWorld world) { + Long2ObjectMap> breakingProgressions = Minecraft.getInstance().worldRenderer.blockBreakingProgressions; + + Int2ObjectMap> breakingEntities = new Int2ObjectArrayMap<>(); + + for (Long2ObjectMap.Entry> entry : breakingProgressions.long2ObjectEntrySet()) { + BlockPos breakingPos = BlockPos.fromLong(entry.getLongKey()); + + SortedSet progresses = entry.getValue(); + if (progresses != null && !progresses.isEmpty()) { + int blockDamage = progresses.last() + .getPartialBlockDamage(); + + TileEntity tileEntity = world.getTileEntity(breakingPos); + + if (tileEntity != null) { + List tileEntities = breakingEntities.computeIfAbsent(blockDamage, $ -> new ArrayList<>()); + tileEntities.add(tileEntity); + } + } + } + + return breakingEntities; + } + + @SubscribeEvent + public static void onReloadRenderers(ReloadRenderersEvent event) { + ClientWorld world = event.getWorld(); + if (Backend.getInstance() + .canUseInstancing() && world != null) { + materialManager.getValue().delete(); + } + } +} 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 e1525c919..5800b0f5a 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -1,44 +1,22 @@ package com.jozufozu.flywheel.backend.instancing; -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.BitSet; -import java.util.SortedSet; -import java.util.Vector; - 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.core.Contexts; -import com.jozufozu.flywheel.core.crumbling.CrumblingInstanceManager; +import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.ReloadRenderersEvent; import com.jozufozu.flywheel.event.RenderLayerEvent; import com.jozufozu.flywheel.util.AnimationTickHolder; import com.jozufozu.flywheel.util.WorldAttached; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.renderer.DestroyBlockProgress; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.client.renderer.model.ModelBakery; -import net.minecraft.client.renderer.texture.Texture; -import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; -import net.minecraft.inventory.container.PlayerContainer; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.LazyValue; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.world.IWorld; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -50,16 +28,10 @@ import net.minecraftforge.fml.common.Mod; @Mod.EventBusSubscriber(Dist.CLIENT) public class InstancedRenderDispatcher { - private static final WorldAttached> entityInstanceManager = new WorldAttached<>(world -> new EntityInstanceManager(Contexts.WORLD.getMaterialManager(world))); - private static final WorldAttached> tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(Contexts.WORLD.getMaterialManager(world))); + private static final WorldAttached> materialManagers = new WorldAttached<>($ -> new MaterialManager<>(Contexts.WORLD)); - private static final LazyValue> blockBreaking = new LazyValue<>(() -> { - Vector renderers = new Vector<>(10); - for (int i = 0; i < 10; i++) { - renderers.add(new CrumblingInstanceManager()); - } - return renderers; - }); + 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))); @Nonnull public static InstanceManager getTiles(IWorld world) { @@ -99,7 +71,7 @@ public class InstancedRenderDispatcher { @SubscribeEvent public static void onBeginFrame(BeginFrameEvent event) { - Contexts.WORLD.getMaterialManager(event.getWorld()) + materialManagers.get(event.getWorld()) .checkAndShiftOrigin(event.getInfo()); getTiles(event.getWorld()).beginFrame(event.getInfo()); @@ -114,7 +86,7 @@ public class InstancedRenderDispatcher { event.type.startDrawing(); - Contexts.WORLD.getMaterialManager(world) + materialManagers.get(world) .render(event.type, event.viewProjection, event.camX, event.camY, event.camZ); event.type.endDrawing(); @@ -129,64 +101,8 @@ public class InstancedRenderDispatcher { } } - private static final RenderType crumblingLayer = ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(0); - - public static void renderBreaking(ClientWorld world, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) { - if (!Backend.getInstance() - .canUseInstancing(world)) return; - - WorldRenderer worldRenderer = Minecraft.getInstance().worldRenderer; - Long2ObjectMap> breakingProgressions = worldRenderer.blockBreakingProgressions; - - if (breakingProgressions.isEmpty()) return; - Vector renderers = blockBreaking.getValue(); - - BitSet bitSet = new BitSet(10); - - for (Long2ObjectMap.Entry> entry : breakingProgressions.long2ObjectEntrySet()) { - BlockPos breakingPos = BlockPos.fromLong(entry.getLongKey()); - - SortedSet progresses = entry.getValue(); - if (progresses != null && !progresses.isEmpty()) { - int blockDamage = progresses.last() - .getPartialBlockDamage(); - bitSet.set(blockDamage); - renderers.get(blockDamage) - .add(world.getTileEntity(breakingPos)); - } - } - - TextureManager textureManager = Minecraft.getInstance().textureManager; - ActiveRenderInfo info = Minecraft.getInstance().gameRenderer.getActiveRenderInfo(); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, textureManager.getTexture(PlayerContainer.BLOCK_ATLAS_TEXTURE) - .getGlTextureId()); - - crumblingLayer.startDrawing(); - bitSet.stream() - .forEach(i -> { - Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(i)); - CrumblingInstanceManager renderer = renderers.get(i); - renderer.beginFrame(info); - - if (breaking != null) { - glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId()); - renderer.materialManager.render(RenderType.getCutoutMipped(), viewProjection, cameraX, cameraY, cameraZ); - } - - renderer.invalidate(); - }); - crumblingLayer.endDrawing(); - - glActiveTexture(GL_TEXTURE0); - Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(0)); - if (breaking != null) glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId()); - } - public static void loadAllInWorld(ClientWorld world) { - Contexts.WORLD.getMaterialManager(world) + materialManagers.get(world) .delete(); InstanceManager tiles = tileInstanceManager.replace(world); 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 ee0c37e07..76a883bad 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java @@ -57,7 +57,7 @@ public class InstancedRenderRegistry { } /** - * @deprecated will be removed in 0.2.0, use {@link #tile} + * @deprecated will be removed in 0.3.0, use {@link #tile} */ @Deprecated public void register(TileEntityType type, ITileInstanceFactory rendererFactory) { @@ -66,7 +66,7 @@ public class InstancedRenderRegistry { } /** - * @deprecated will be removed in 0.2.0, use {@link #entity} + * @deprecated will be removed in 0.3.0, use {@link #entity} */ @Deprecated public void register(EntityType type, IEntityInstanceFactory rendererFactory) { diff --git a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java index a387fea1c..44d125f1f 100644 --- a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java +++ b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java @@ -12,7 +12,6 @@ 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.MaterialManager; import com.jozufozu.flywheel.backend.instancing.MaterialSpec; import com.jozufozu.flywheel.backend.loading.InstancedArraysTemplate; import com.jozufozu.flywheel.backend.loading.Program; @@ -23,10 +22,8 @@ import com.jozufozu.flywheel.backend.loading.ShaderTransformer; import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram; import com.jozufozu.flywheel.core.shader.StateSensitiveMultiProgram; import com.jozufozu.flywheel.core.shader.WorldProgram; -import com.jozufozu.flywheel.util.WorldAttached; import net.minecraft.util.ResourceLocation; -import net.minecraft.world.IWorld; public class WorldContext

extends ShaderContext

{ @@ -37,8 +34,6 @@ public class WorldContext

extends ShaderContext

{ protected Supplier> specStream; protected TemplateFactory templateFactory; - private final WorldAttached> worldAttachedMMs = new WorldAttached<>($ -> new MaterialManager<>(this)); - private final Map builtins = new EnumMap<>(ShaderType.class); private final Map builtinSources = new EnumMap<>(ShaderType.class); @@ -69,10 +64,6 @@ public class WorldContext

extends ShaderContext

{ return this; } - public MaterialManager

getMaterialManager(IWorld world) { - return worldAttachedMMs.get(world); - } - public WorldContext

withSpecStream(Supplier> specStream) { this.specStream = specStream; return this; @@ -122,13 +113,6 @@ public class WorldContext

extends ShaderContext

{ }); } - @Override - public void delete() { - super.delete(); - - worldAttachedMMs.empty(MaterialManager::delete); - } - @Override protected Shader getSource(ShaderType type, ResourceLocation name) { Shader source = super.getSource(type, name); 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 708f800ab..3e3446a88 100644 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java @@ -1,12 +1,14 @@ package com.jozufozu.flywheel.core.crumbling; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; import net.minecraft.util.math.BlockPos; public class CrumblingInstanceManager extends TileInstanceManager { - public CrumblingInstanceManager() { - super(new CrumblingMaterialManager()); + + public CrumblingInstanceManager(MaterialManager materialManager) { + super(materialManager); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingMaterialManager.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingMaterialManager.java index 5d9a01754..9d8974ade 100644 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingMaterialManager.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingMaterialManager.java @@ -10,7 +10,7 @@ import java.util.Map; import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.jozufozu.flywheel.backend.instancing.MaterialRenderer; -import com.jozufozu.flywheel.core.Contexts; +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; @@ -24,8 +24,8 @@ import net.minecraft.util.math.vector.Matrix4f; public class CrumblingMaterialManager extends MaterialManager { - public CrumblingMaterialManager() { - super(Contexts.CRUMBLING); + public CrumblingMaterialManager(WorldContext context) { + super(context); } /** diff --git a/src/main/java/com/jozufozu/flywheel/core/package-info.java b/src/main/java/com/jozufozu/flywheel/core/package-info.java new file mode 100644 index 000000000..4cef387dc --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.jozufozu.flywheel.core; + +import javax.annotation.ParametersAreNonnullByDefault; + +import mcp.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java index c28b21686..7ef6abf64 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java @@ -9,6 +9,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.OptifineHandler; +import com.jozufozu.flywheel.backend.instancing.CrumblingRenderer; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.ReloadRenderersEvent; @@ -81,7 +82,7 @@ public class RenderHooksMixin { .getProjectionMatrix()); Vector3d cameraPos = info.getProjectedView(); - InstancedRenderDispatcher.renderBreaking(world, viewProjection, cameraPos.x, cameraPos.y, cameraPos.z); + CrumblingRenderer.renderBreaking(world, viewProjection, cameraPos.x, cameraPos.y, cameraPos.z); if (!OptifineHandler.usingShaders()) GL20.glUseProgram(0); } diff --git a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java index 2859ad40b..4d4d944e9 100644 --- a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java +++ b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java @@ -12,7 +12,7 @@ import net.minecraft.world.IWorld; public class WorldAttached { - Map attached; + private final Map attached; private final Function factory; public WorldAttached(Function factory) {