diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index 64cebacd5..26f1cb4bb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -1,19 +1,10 @@ package com.jozufozu.flywheel.backend; -import static org.lwjgl.opengl.GL20.GL_TEXTURE0; -import static org.lwjgl.opengl.GL20.GL_TEXTURE4; -import static org.lwjgl.opengl.GL20.GL_TEXTURE_2D; -import static org.lwjgl.opengl.GL20.glActiveTexture; -import static org.lwjgl.opengl.GL20.glBindTexture; - import java.util.ArrayList; -import java.util.BitSet; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.SortedSet; -import java.util.Vector; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -23,56 +14,27 @@ import org.lwjgl.opengl.GLCapabilities; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; import com.jozufozu.flywheel.backend.instancing.InstanceData; -import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.jozufozu.flywheel.backend.instancing.MaterialSpec; -import com.jozufozu.flywheel.backend.instancing.TileInstanceManager; -import com.jozufozu.flywheel.core.CrumblingInstanceManager; -import com.jozufozu.flywheel.core.QuadConverter; import com.jozufozu.flywheel.core.WorldContext; -import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; -import com.jozufozu.flywheel.util.WorldAttached; import com.simibubi.create.foundation.config.AllConfigs; -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.resources.IReloadableResourceManager; import net.minecraft.resources.IResourceManager; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.LazyValue; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.world.IWorld; import net.minecraft.world.World; public class Backend { public static final Logger log = LogManager.getLogger(Backend.class); - public static final ShaderLoader shaderLoader = new ShaderLoader(); - public static final FlywheelListeners listeners = new FlywheelListeners(); + public static final ShaderSources SHADER_SOURCES = new ShaderSources(); public static GLCapabilities capabilities; public static GlCompat compat; - public static WorldAttached tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(WorldContext.INSTANCE.getMaterialManager(world))); - public static LazyValue> blockBreaking = new LazyValue<>(() -> { - Vector renderers = new Vector<>(10); - for (int i = 0; i < 10; i++) { - renderers.add(new CrumblingInstanceManager()); - } - return renderers; - }); - private static Matrix4f projectionMatrix = new Matrix4f(); private static boolean instancedArrays; private static boolean enabled; @@ -84,26 +46,6 @@ public class Backend { static { register(WorldContext.INSTANCE); register(WorldContext.CRUMBLING); - - listeners.refreshListener(world -> { - if (canUseInstancing() && world != null) { - TileInstanceManager tileRenderer = Backend.tileInstanceManager.get(world); - tileRenderer.invalidate(); - world.loadedTileEntityList.forEach(tileRenderer::add); - } - - QuadConverter quadConverter = QuadConverter.getNullable(); - if (quadConverter != null) quadConverter.free(); - }); - - listeners.setupFrameListener((world, stack, info, gameRenderer, lightTexture) -> { - WorldContext.INSTANCE.materialManager.get(world) - .checkAndShiftOrigin(info); - Backend.tileInstanceManager.get(world) - .beginFrame(info); - }); - - listeners.renderLayerListener(Backend::renderLayer); } public Backend() { @@ -165,7 +107,7 @@ public class Backend { /** * Used to avoid calling Flywheel functions on (fake) worlds that don't specifically support it. */ - public static boolean isFlywheelWorld(World world) { + public static boolean isFlywheelWorld(IWorld world) { return (world instanceof IFlywheelWorld && ((IFlywheelWorld) world).supportsFlywheel()) || world == Minecraft.getInstance().world; } @@ -197,8 +139,10 @@ public class Backend { IResourceManager manager = mc.getResourceManager(); if (manager instanceof IReloadableResourceManager) { - ((IReloadableResourceManager) manager).addReloadListener(shaderLoader); + ((IReloadableResourceManager) manager).addReloadListener(SHADER_SOURCES); } + + OptifineHandler.init(); } public static void refresh() { @@ -213,84 +157,6 @@ public class Backend { enabled = AllConfigs.CLIENT.experimentalRendering.get() && !OptifineHandler.usingShaders(); } - public static void tick() { - Minecraft mc = Minecraft.getInstance(); - ClientWorld world = mc.world; - - TileInstanceManager instancer = tileInstanceManager.get(world); - - Entity renderViewEntity = mc.renderViewEntity; - instancer.tick(renderViewEntity.getX(), renderViewEntity.getY(), renderViewEntity.getZ()); - } - - public static void renderLayer(ClientWorld world, RenderType layer, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) { - if (!canUseInstancing(world)) return; - MaterialManager materialManager = WorldContext.INSTANCE.getMaterialManager(world); - - layer.startDrawing(); - - materialManager.render(layer, viewProjection, cameraX, cameraY, cameraZ); - - layer.endDrawing(); - } - - private static final RenderType CRUMBLING = ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(0); - - public static void renderBreaking(ClientWorld world, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) { - if (!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()); - - glActiveTexture(GL_TEXTURE4); - - CRUMBLING.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) { - glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId()); - renderer.materialManager.render(RenderType.getCutoutMipped(), viewProjection, cameraX, cameraY, cameraZ); - } - - renderer.invalidate(); - }); - CRUMBLING.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 enqueueUpdate(TileEntity te) { - tileInstanceManager.get(te.getWorld()).queueUpdate(te); - } - public static void reloadWorldRenderers() { RenderWork.enqueue(Minecraft.getInstance().worldRenderer::loadRenderers); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/FlywheelListeners.java b/src/main/java/com/jozufozu/flywheel/backend/FlywheelListeners.java deleted file mode 100644 index f0f86b5a8..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/FlywheelListeners.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.jozufozu.flywheel.backend; - -import java.util.ArrayList; -import java.util.List; - -import com.mojang.blaze3d.matrix.MatrixStack; - -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.util.math.vector.Matrix4f; - -public class FlywheelListeners { - - private final List setupFrameListeners = new ArrayList<>(); - private final List renderLayerListeners = new ArrayList<>(); - private final List refreshListeners = new ArrayList<>(); - - public void setupFrameListener(SetupFrame setupFrame) { - setupFrameListeners.add(setupFrame); - } - - public void renderLayerListener(RenderLayer renderLayer) { - renderLayerListeners.add(renderLayer); - } - - public void refreshListener(Refresh refresh) { - refreshListeners.add(refresh); - } - - public void setupFrame(ClientWorld world, MatrixStack stack, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture) { - for (SetupFrame listener : setupFrameListeners) { - listener.setupFrame(world, stack, info, gameRenderer, lightTexture); - } - } - - public void renderLayer(ClientWorld world, RenderType type, Matrix4f stack, double camX, double camY, double camZ) { - for (RenderLayer listener : renderLayerListeners) { - listener.renderLayer(world, type, stack, camX, camY, camZ); - } - } - - public void refresh(ClientWorld world) { - for (Refresh listener : refreshListeners) { - listener.refresh(world); - } - } - - @FunctionalInterface - public interface SetupFrame { - void setupFrame(ClientWorld world, MatrixStack stack, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture); - } - - @FunctionalInterface - public interface RenderLayer { - void renderLayer(ClientWorld world, RenderType type, Matrix4f viewProjection, double camX, double camY, double camZ); - } - - @FunctionalInterface - public interface Refresh { - void refresh(ClientWorld world); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/RenderWork.java b/src/main/java/com/jozufozu/flywheel/backend/RenderWork.java index 1e197860c..8a418247e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/RenderWork.java +++ b/src/main/java/com/jozufozu/flywheel/backend/RenderWork.java @@ -3,10 +3,18 @@ package com.jozufozu.flywheel.backend; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber public class RenderWork { private static final Queue runs = new ConcurrentLinkedQueue<>(); - public static void runAll() { + + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void onRenderWorldLast(RenderWorldLastEvent event) { while (!runs.isEmpty()) { runs.remove().run(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java b/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java index e93aeae41..9f399045d 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java +++ b/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java @@ -20,18 +20,19 @@ public abstract class ShaderContext

{ protected ShaderTransformer transformer = new ShaderTransformer(); - public ShaderContext() { } + public ShaderContext() { + } // TODO: Untangle the loading functions /** * Load all programs associated with this context. This might be just one, if the context is very specialized. */ - public abstract void load(ShaderLoader loader); + public abstract void load(ShaderSources loader); - protected abstract IMultiProgram

loadSpecInternal(ShaderLoader loader, ProgramSpec spec); + protected abstract IMultiProgram

loadSpecInternal(ShaderSources loader, ProgramSpec spec); - public void loadProgramFromSpec(ShaderLoader loader, ProgramSpec programSpec) { + public void loadProgramFromSpec(ShaderSources loader, ProgramSpec programSpec) { try { programs.put(programSpec.name, loadSpecInternal(loader, programSpec)); @@ -43,7 +44,7 @@ public abstract class ShaderContext

{ } } - public Program loadProgram(ShaderLoader loader, ProgramSpec spec, Collection defines) { + public Program loadProgram(ShaderSources loader, ProgramSpec spec, Collection defines) { Shader vertexFile = loader.source(spec.vert, ShaderType.VERTEX); Shader fragmentFile = loader.source(spec.frag, ShaderType.FRAGMENT); diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShaderLoader.java b/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java similarity index 84% rename from src/main/java/com/jozufozu/flywheel/backend/ShaderLoader.java rename to src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java index 5bab05133..9da3de4cc 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/ShaderLoader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java @@ -12,14 +12,9 @@ import java.nio.channels.ReadableByteChannel; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.function.Predicate; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.Nonnull; @@ -52,14 +47,11 @@ import net.minecraftforge.resource.ISelectiveResourceReloadListener; import net.minecraftforge.resource.VanillaResourceType; @ParametersAreNonnullByDefault -public class ShaderLoader implements ISelectiveResourceReloadListener { +public class ShaderSources implements ISelectiveResourceReloadListener { public static final String SHADER_DIR = "flywheel/shaders/"; public static final String PROGRAM_DIR = "flywheel/programs/"; public static final ArrayList EXTENSIONS = Lists.newArrayList(".vert", ".vsh", ".frag", ".fsh", ".glsl"); - // #flwinclude <"valid_namespace:valid/path_to_file.glsl"> - private static final Pattern includePattern = Pattern.compile("#flwinclude <\"([\\w\\d_]+:[\\w\\d_./]+)\">"); - private final Map shaderSource = new HashMap<>(); private boolean shouldCrash; @@ -161,7 +153,7 @@ public class ShaderLoader implements ISelectiveResourceReloadListener { } public Shader source(ResourceLocation name, ShaderType type) { - return new Shader(type, name, getShaderSource(name)); + return new Shader(this, type, name, getShaderSource(name)); } public Program loadProgram(ResourceLocation name, Shader... shaders) { @@ -201,38 +193,6 @@ public class ShaderLoader implements ISelectiveResourceReloadListener { } } - public void processIncludes(Shader shader) { - HashSet seen = new HashSet<>(); - seen.add(shader.name); - - String includesInjected = includeRecursive(shader.getSource(), seen).collect(Collectors.joining("\n")); - shader.setSource(includesInjected); - } - - private Stream includeRecursive(String source, Set seen) { - return lines(source).flatMap(line -> { - - Matcher matcher = includePattern.matcher(line); - - if (matcher.find()) { - String includeName = matcher.group(1); - - ResourceLocation include = new ResourceLocation(includeName); - - if (seen.add(include)) { - try { - return includeRecursive(getShaderSource(include), seen); - } catch (ShaderLoadingException e) { - throw new ShaderLoadingException("could not resolve import: " + e.getMessage()); - } - } - - } - - return Stream.of(line); - }); - } - public static Stream lines(String s) { return new BufferedReader(new StringReader(s)).lines(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceMaterial.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceMaterial.java index 5f9671fc0..89d1a9dea 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceMaterial.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceMaterial.java @@ -49,8 +49,8 @@ public class InstanceMaterial { this.models = CacheBuilder.newBuilder() .removalListener(notification -> { - Instancer model = (Instancer) notification.getValue(); - RenderWork.enqueue(model::delete); + Instancer instancer = (Instancer) notification.getValue(); + RenderWork.enqueue(instancer::delete); }) .build(); modelFormat = this.spec.getModelFormat(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java new file mode 100644 index 000000000..a30b59188 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -0,0 +1,160 @@ +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.core.CrumblingInstanceManager; +import com.jozufozu.flywheel.core.WorldContext; +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.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.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber +public class InstancedRenderDispatcher { + + private static final RenderType CRUMBLING = ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(0); + + private static final WorldAttached tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(WorldContext.INSTANCE.getMaterialManager(world))); + public static LazyValue> blockBreaking = new LazyValue<>(() -> { + Vector renderers = new Vector<>(10); + for (int i = 0; i < 10; i++) { + renderers.add(new CrumblingInstanceManager()); + } + return renderers; + }); + + @Nonnull + public static TileInstanceManager get(IWorld world) { + return tileInstanceManager.get(world); + } + + public static void tick() { + Minecraft mc = Minecraft.getInstance(); + ClientWorld world = mc.world; + + TileInstanceManager instancer = get(world); + + Entity renderViewEntity = mc.renderViewEntity; + instancer.tick(renderViewEntity.getX(), renderViewEntity.getY(), renderViewEntity.getZ()); + } + + public static void enqueueUpdate(TileEntity te) { + get(te.getWorld()).queueUpdate(te); + } + + @SubscribeEvent + public static void onBeginFrame(BeginFrameEvent event) { + WorldContext.INSTANCE.getMaterialManager(event.getWorld()) + .checkAndShiftOrigin(event.getInfo()); + get(event.getWorld()) + .beginFrame(event.getInfo()); + } + + @SubscribeEvent + public static void renderLayer(RenderLayerEvent event) { + ClientWorld world = event.getWorld(); + if (!Backend.canUseInstancing(world)) return; + MaterialManager materialManager = WorldContext.INSTANCE.getMaterialManager(world); + + event.type.startDrawing(); + + materialManager.render(event.type, event.viewProjection, event.camX, event.camY, event.camZ); + + event.type.endDrawing(); + } + + @SubscribeEvent + public static void onReloadRenderers(ReloadRenderersEvent event) { + ClientWorld world = event.getWorld(); + if (Backend.canUseInstancing() && world != null) { + WorldContext.INSTANCE.getMaterialManager(world).delete(); + + TileInstanceManager tileRenderer = get(world); + tileRenderer.invalidate(); + world.loadedTileEntityList.forEach(tileRenderer::add); + } + } + + public static void renderBreaking(ClientWorld world, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) { + if (!Backend.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()); + + glActiveTexture(GL_TEXTURE4); + + CRUMBLING.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) { + glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId()); + renderer.materialManager.render(RenderType.getCutoutMipped(), viewProjection, cameraX, cameraY, cameraZ); + } + + renderer.invalidate(); + }); + CRUMBLING.endDrawing(); + + glActiveTexture(GL_TEXTURE0); + Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(0)); + if (breaking != null) + glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId()); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/TileInstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/TileInstanceManager.java index ca1b98711..114d1a857 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/TileInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/TileInstanceManager.java @@ -9,6 +9,7 @@ import javax.annotation.Nullable; import com.jozufozu.flywheel.backend.Backend; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; @@ -24,8 +25,8 @@ public class TileInstanceManager implements MaterialManager.OriginShiftListener protected final ConcurrentHashMap.KeySetView queuedUpdates; protected final Map> instances; - protected final Map tickableInstances; - protected final Map dynamicInstances; + protected final Object2ObjectOpenHashMap tickableInstances; + protected final Object2ObjectOpenHashMap dynamicInstances; protected int frame; protected int tick; @@ -34,10 +35,11 @@ public class TileInstanceManager implements MaterialManager.OriginShiftListener this.materialManager = materialManager; this.queuedUpdates = ConcurrentHashMap.newKeySet(64); this.queuedAdditions = new ArrayList<>(64); - this.dynamicInstances = new HashMap<>(); - this.tickableInstances = new HashMap<>(); this.instances = new HashMap<>(); + this.dynamicInstances = new Object2ObjectOpenHashMap<>(); + this.tickableInstances = new Object2ObjectOpenHashMap<>(); + materialManager.onOriginShift(this); } @@ -89,10 +91,11 @@ public class TileInstanceManager implements MaterialManager.OriginShiftListener int cZ = (int) info.getProjectedView().z; if (dynamicInstances.size() > 0) { - for (IDynamicInstance dyn : dynamicInstances.values()) { - if (!dyn.decreaseFramerateWithDistance() || shouldTick(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ)) + dynamicInstances.object2ObjectEntrySet().fastForEach(e -> { + IDynamicInstance dyn = e.getValue(); + if (!dyn.decreaseFramerateWithDistance() || shouldFrameUpdate(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ)) dyn.beginFrame(); - } + }); } } @@ -184,14 +187,15 @@ public class TileInstanceManager implements MaterialManager.OriginShiftListener } } - protected boolean shouldTick(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) { + protected boolean shouldFrameUpdate(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) { int dX = worldPos.getX() - cX; int dY = worldPos.getY() - cY; int dZ = worldPos.getZ() - cZ; - float dot = (dX + lookX * 2) * lookX + (dY + lookY * 2) * lookY + (dZ + lookZ * 2) * lookZ; - - if (dot < 0) return false; // is it more than 2 blocks behind the camera? + // is it more than 2 blocks behind the camera? + int dist = 2; + float dot = (dX + lookX * dist) * lookX + (dY + lookY * dist) * lookY + (dZ + lookZ * dist) * lookZ; + if (dot < 0) return false; return (frame % getUpdateDivisor(dX, dY, dZ)) == 0; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/InstancedArraysTemplate.java b/src/main/java/com/jozufozu/flywheel/backend/loading/InstancedArraysTemplate.java index 6f3c6cd84..9d1ba5841 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/InstancedArraysTemplate.java +++ b/src/main/java/com/jozufozu/flywheel/backend/loading/InstancedArraysTemplate.java @@ -1,7 +1,7 @@ package com.jozufozu.flywheel.backend.loading; import com.jozufozu.flywheel.Flywheel; -import com.jozufozu.flywheel.backend.ShaderLoader; +import com.jozufozu.flywheel.backend.ShaderSources; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import net.minecraft.util.ResourceLocation; @@ -22,7 +22,7 @@ public class InstancedArraysTemplate extends ProgramTemplate { public static final ResourceLocation vert = new ResourceLocation(Flywheel.ID, "template/instanced/instanced.vert"); public static final ResourceLocation frag = new ResourceLocation(Flywheel.ID, "template/instanced/instanced.frag"); - public InstancedArraysTemplate(ShaderLoader loader) { + public InstancedArraysTemplate(ShaderSources loader) { super(loader); templates.put(ShaderType.VERTEX, new ShaderTemplate(requiredVert, loader.getShaderSource(vert))); diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/ModelTemplate.java b/src/main/java/com/jozufozu/flywheel/backend/loading/ModelTemplate.java index 5e12d8652..74e3810b1 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/ModelTemplate.java +++ b/src/main/java/com/jozufozu/flywheel/backend/loading/ModelTemplate.java @@ -1,7 +1,7 @@ package com.jozufozu.flywheel.backend.loading; import com.jozufozu.flywheel.Flywheel; -import com.jozufozu.flywheel.backend.ShaderLoader; +import com.jozufozu.flywheel.backend.ShaderSources; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import net.minecraft.util.ResourceLocation; @@ -19,7 +19,7 @@ public class ModelTemplate extends ProgramTemplate { public static final ResourceLocation vert = new ResourceLocation(Flywheel.ID, "template/model/model.vert"); public static final ResourceLocation frag = new ResourceLocation(Flywheel.ID, "template/model/model.frag"); - public ModelTemplate(ShaderLoader loader) { + public ModelTemplate(ShaderSources loader) { super(loader); templates.put(ShaderType.VERTEX, new ShaderTemplate(requiredVert, loader.getShaderSource(vert))); diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/ProgramTemplate.java b/src/main/java/com/jozufozu/flywheel/backend/loading/ProgramTemplate.java index 70c93ece9..a04f004fa 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/ProgramTemplate.java +++ b/src/main/java/com/jozufozu/flywheel/backend/loading/ProgramTemplate.java @@ -3,15 +3,15 @@ package com.jozufozu.flywheel.backend.loading; import java.util.EnumMap; import java.util.Map; -import com.jozufozu.flywheel.backend.ShaderLoader; +import com.jozufozu.flywheel.backend.ShaderSources; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; public abstract class ProgramTemplate implements IProcessingStage { - protected final ShaderLoader loader; + protected final ShaderSources loader; protected Map templates = new EnumMap<>(ShaderType.class); - public ProgramTemplate(ShaderLoader loader) { + public ProgramTemplate(ShaderSources loader) { this.loader = loader; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/Shader.java b/src/main/java/com/jozufozu/flywheel/backend/loading/Shader.java index 250172968..c572c1d27 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/Shader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/loading/Shader.java @@ -1,32 +1,43 @@ package com.jozufozu.flywheel.backend.loading; +import java.io.BufferedReader; +import java.io.StringReader; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.Stream; +import com.jozufozu.flywheel.backend.ShaderSources; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import net.minecraft.util.ResourceLocation; public class Shader { + // #flwinclude <"valid_namespace:valid/path_to_file.glsl"> + private static final Pattern includePattern = Pattern.compile("#flwinclude <\"([\\w\\d_]+:[\\w\\d_./]+)\">"); + public static final Pattern versionDetector = Pattern.compile("#version[^\\n]*"); private static final Pattern decorator = Pattern.compile("#\\[([\\w_]*)]"); public final ResourceLocation name; public ShaderType type; private String source; + private final ShaderSources loader; private boolean parsed = false; final List structs = new ArrayList<>(3); final Map tag2Struct = new HashMap<>(); final Map name2Struct = new HashMap<>(); - public Shader(ShaderType type, ResourceLocation name, String source) { + public Shader(ShaderSources loader, ShaderType type, ResourceLocation name, String source) { + this.loader = loader; this.type = type; this.name = name; this.source = source; @@ -91,4 +102,39 @@ public class Shader { this.source = strippedSrc.toString(); } + + public void processIncludes() { + HashSet seen = new HashSet<>(); + seen.add(name); + + source = includeRecursive(source, seen).collect(Collectors.joining("\n")); + } + + private Stream includeRecursive(String source, Set seen) { + return lines(source).flatMap(line -> { + + Matcher matcher = includePattern.matcher(line); + + if (matcher.find()) { + String includeName = matcher.group(1); + + ResourceLocation include = new ResourceLocation(includeName); + + if (seen.add(include)) { + try { + return includeRecursive(loader.getShaderSource(include), seen); + } catch (ShaderLoadingException e) { + throw new ShaderLoadingException("could not resolve import: " + e.getMessage()); + } + } + + } + + return Stream.of(line); + }); + } + + public static Stream lines(String s) { + return new BufferedReader(new StringReader(s)).lines(); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/CrumblingInstanceManager.java b/src/main/java/com/jozufozu/flywheel/core/CrumblingInstanceManager.java index 6ff67a6b4..48f1589ec 100644 --- a/src/main/java/com/jozufozu/flywheel/core/CrumblingInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/core/CrumblingInstanceManager.java @@ -11,7 +11,7 @@ public class CrumblingInstanceManager extends TileInstanceManager { } @Override - protected boolean shouldTick(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) { + protected boolean shouldFrameUpdate(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) { return true; } } diff --git a/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java b/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java index 1993a043c..a00f339e6 100644 --- a/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java +++ b/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java @@ -15,10 +15,16 @@ import com.jozufozu.flywheel.backend.gl.GlNumericType; import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.model.ElementBuffer; +import com.jozufozu.flywheel.event.ReloadRenderersEvent; + +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; /** * A class to manage EBOs that index quads as triangles. */ +@Mod.EventBusSubscriber public class QuadConverter { public static final int STARTING_CAPACITY = 42; @@ -158,4 +164,10 @@ public class QuadConverter { return GlNumericType.UINT; } + + // make sure this gets reset first so it has a chance to repopulate + @SubscribeEvent(priority = EventPriority.HIGHEST) + public static void onRendererReload(ReloadRenderersEvent event) { + if (INSTANCE != null) INSTANCE.free(); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java index 95130b847..5246eb135 100644 --- a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java +++ b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java @@ -11,7 +11,7 @@ import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.ResourceUtil; import com.jozufozu.flywheel.backend.ShaderContext; -import com.jozufozu.flywheel.backend.ShaderLoader; +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; @@ -43,7 +43,7 @@ public class WorldContext

extends ShaderContext

{ protected Supplier> specStream; protected TemplateFactory templateFactory; - public final WorldAttached> materialManager = new WorldAttached<>($ -> new MaterialManager<>(this)); + private final WorldAttached> materialManager = new WorldAttached<>($ -> new MaterialManager<>(this)); private final Map builtins = new EnumMap<>(ShaderType.class); private final Map builtinSources = new EnumMap<>(ShaderType.class); @@ -78,13 +78,14 @@ public class WorldContext

extends ShaderContext

{ } @Override - protected IMultiProgram

loadSpecInternal(ShaderLoader loader, ProgramSpec spec) { + protected IMultiProgram

loadSpecInternal(ShaderSources loader, ProgramSpec spec) { return new StateSensitiveMultiProgram<>(loader, factory, this, spec); } protected ProgramTemplate template; + @Override - public void load(ShaderLoader loader) { + public void load(ShaderSources loader) { programs.values().forEach(IMultiProgram::delete); programs.clear(); @@ -103,10 +104,10 @@ public class WorldContext

extends ShaderContext

{ template = templateFactory.create(loader); transformer = new ShaderTransformer() .pushStage(this::injectBuiltins) - .pushStage(loader::processIncludes) + .pushStage(Shader::processIncludes) .pushStage(Shader::parseStructs) .pushStage(template) - .pushStage(loader::processIncludes); + .pushStage(Shader::processIncludes); specStream.get() .map(Backend::getSpec) @@ -131,6 +132,6 @@ public class WorldContext

extends ShaderContext

{ } public interface TemplateFactory { - ProgramTemplate create(ShaderLoader loader); + ProgramTemplate create(ShaderSources loader); } } diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/StateSensitiveMultiProgram.java b/src/main/java/com/jozufozu/flywheel/core/shader/StateSensitiveMultiProgram.java index e48a86bc5..597d6ef2f 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/StateSensitiveMultiProgram.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/StateSensitiveMultiProgram.java @@ -5,7 +5,7 @@ import java.util.Collections; import java.util.List; import com.jozufozu.flywheel.backend.ShaderContext; -import com.jozufozu.flywheel.backend.ShaderLoader; +import com.jozufozu.flywheel.backend.ShaderSources; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.loading.Program; import com.jozufozu.flywheel.core.shader.spec.IContextCondition; @@ -18,7 +18,7 @@ public class StateSensitiveMultiProgram

implements IMultiPr List> variants; P fallback; - public StateSensitiveMultiProgram(ShaderLoader loader, ExtensibleGlProgram.Factory

factory, ShaderContext

context, ProgramSpec p) { + public StateSensitiveMultiProgram(ShaderSources loader, ExtensibleGlProgram.Factory

factory, ShaderContext

context, ProgramSpec p) { variants = new ArrayList<>(p.states.size()); for (ProgramState state : p.states) { diff --git a/src/main/java/com/jozufozu/flywheel/event/BeginFrameEvent.java b/src/main/java/com/jozufozu/flywheel/event/BeginFrameEvent.java new file mode 100644 index 000000000..042cc1acd --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/event/BeginFrameEvent.java @@ -0,0 +1,45 @@ +package com.jozufozu.flywheel.event; + +import com.mojang.blaze3d.matrix.MatrixStack; + +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.world.ClientWorld; +import net.minecraftforge.eventbus.api.Event; + +public class BeginFrameEvent extends Event { + private final ClientWorld world; + private final MatrixStack stack; + private final ActiveRenderInfo info; + private final GameRenderer gameRenderer; + private final LightTexture lightTexture; + + public BeginFrameEvent(ClientWorld world, MatrixStack stack, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture) { + this.world = world; + this.stack = stack; + this.info = info; + this.gameRenderer = gameRenderer; + this.lightTexture = lightTexture; + } + + public ClientWorld getWorld() { + return world; + } + + public MatrixStack getStack() { + return stack; + } + + public ActiveRenderInfo getInfo() { + return info; + } + + public GameRenderer getGameRenderer() { + return gameRenderer; + } + + public LightTexture getLightTexture() { + return lightTexture; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java index c77665233..744ad8ea2 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java @@ -3,9 +3,14 @@ package com.jozufozu.flywheel.event; import java.util.ArrayList; import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.backend.instancing.TileInstanceManager; import net.minecraft.client.Minecraft; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.world.IWorld; import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; @@ -29,4 +34,15 @@ public class ForgeEvents { } } } + + @SubscribeEvent + public static void onLoadWorld(WorldEvent.Load event) { + IWorld world = event.getWorld(); + + if (Backend.isFlywheelWorld(world)) { + TileInstanceManager renderer = InstancedRenderDispatcher.get(world); + renderer.invalidate(); + ((ClientWorld) world).loadedTileEntityList.forEach(renderer::add); + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/event/ReloadRenderersEvent.java b/src/main/java/com/jozufozu/flywheel/event/ReloadRenderersEvent.java new file mode 100644 index 000000000..dc7bac5fb --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/event/ReloadRenderersEvent.java @@ -0,0 +1,16 @@ +package com.jozufozu.flywheel.event; + +import net.minecraft.client.world.ClientWorld; +import net.minecraftforge.eventbus.api.Event; + +public class ReloadRenderersEvent extends Event { + private final ClientWorld world; + + public ReloadRenderersEvent(ClientWorld world) { + this.world = world; + } + + public ClientWorld getWorld() { + return world; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/event/RenderLayerEvent.java b/src/main/java/com/jozufozu/flywheel/event/RenderLayerEvent.java new file mode 100644 index 000000000..a22816f71 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/event/RenderLayerEvent.java @@ -0,0 +1,48 @@ +package com.jozufozu.flywheel.event; + +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraftforge.eventbus.api.Event; + +public class RenderLayerEvent extends Event { + private final ClientWorld world; + public final RenderType type; + public final Matrix4f viewProjection; + public final double camX; + public final double camY; + public final double camZ; + + public RenderLayerEvent(ClientWorld world, RenderType type, Matrix4f viewProjection, double camX, double camY, double camZ) { + this.world = world; + this.type = type; + this.viewProjection = viewProjection; + this.camX = camX; + this.camY = camY; + this.camZ = camZ; + } + + public ClientWorld getWorld() { + return world; + } + + public RenderType getType() { + return type; + } + + public Matrix4f getViewProjection() { + return viewProjection; + } + + public double getCamX() { + return camX; + } + + public double getCamY() { + return camY; + } + + public double getCamZ() { + return camZ; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/light/LightVolume.java b/src/main/java/com/jozufozu/flywheel/light/LightVolume.java index 2e5550482..c27ad19f3 100644 --- a/src/main/java/com/jozufozu/flywheel/light/LightVolume.java +++ b/src/main/java/com/jozufozu/flywheel/light/LightVolume.java @@ -1,15 +1,33 @@ package com.jozufozu.flywheel.light; +import static org.lwjgl.opengl.GL20.GL_LINEAR; +import static org.lwjgl.opengl.GL20.GL_MIRRORED_REPEAT; +import static org.lwjgl.opengl.GL20.GL_TEXTURE0; +import static org.lwjgl.opengl.GL20.GL_TEXTURE4; +import static org.lwjgl.opengl.GL20.GL_TEXTURE_3D; +import static org.lwjgl.opengl.GL20.GL_TEXTURE_MAG_FILTER; +import static org.lwjgl.opengl.GL20.GL_TEXTURE_MIN_FILTER; +import static org.lwjgl.opengl.GL20.GL_TEXTURE_WRAP_R; +import static org.lwjgl.opengl.GL20.GL_TEXTURE_WRAP_S; +import static org.lwjgl.opengl.GL20.GL_TEXTURE_WRAP_T; +import static org.lwjgl.opengl.GL20.GL_UNPACK_ALIGNMENT; +import static org.lwjgl.opengl.GL20.GL_UNPACK_IMAGE_HEIGHT; +import static org.lwjgl.opengl.GL20.GL_UNPACK_ROW_LENGTH; +import static org.lwjgl.opengl.GL20.GL_UNPACK_SKIP_IMAGES; +import static org.lwjgl.opengl.GL20.GL_UNPACK_SKIP_PIXELS; +import static org.lwjgl.opengl.GL20.GL_UNPACK_SKIP_ROWS; +import static org.lwjgl.opengl.GL20.GL_UNSIGNED_BYTE; +import static org.lwjgl.opengl.GL20.glActiveTexture; +import static org.lwjgl.opengl.GL20.glPixelStorei; +import static org.lwjgl.opengl.GL20.glTexImage3D; +import static org.lwjgl.opengl.GL20.glTexParameteri; +import static org.lwjgl.opengl.GL20.glTexSubImage3D; + import java.nio.ByteBuffer; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL12; -import org.lwjgl.opengl.GL13; -import org.lwjgl.opengl.GL20; import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.RenderWork; import com.jozufozu.flywheel.backend.gl.GlTexture; import com.jozufozu.flywheel.backend.gl.versioned.RGPixelFormat; @@ -35,20 +53,20 @@ public class LightVolume { pixelFormat = Backend.compat.pixelFormat; - this.glTexture = new GlTexture(GL20.GL_TEXTURE_3D); + this.glTexture = new GlTexture(GL_TEXTURE_3D); this.lightData = MemoryUtil.memAlloc(this.textureVolume.volume() * pixelFormat.byteCount()); // allocate space for the texture - GL20.glActiveTexture(GL20.GL_TEXTURE4); + glActiveTexture(GL_TEXTURE4); glTexture.bind(); int sizeX = textureVolume.sizeX(); int sizeY = textureVolume.sizeY(); int sizeZ = textureVolume.sizeZ(); - GL12.glTexImage3D(GL12.GL_TEXTURE_3D, 0, pixelFormat.internalFormat(), sizeX, sizeY, sizeZ, 0, pixelFormat.format(), GL20.GL_UNSIGNED_BYTE, 0); + glTexImage3D(GL_TEXTURE_3D, 0, pixelFormat.internalFormat(), sizeX, sizeY, sizeZ, 0, pixelFormat.format(), GL_UNSIGNED_BYTE, 0); glTexture.unbind(); - GL20.glActiveTexture(GL20.GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0); } private void setSampleVolume(GridAlignedBB sampleVolume) { @@ -242,32 +260,32 @@ 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; - GL13.glActiveTexture(GL20.GL_TEXTURE4); + glActiveTexture(GL_TEXTURE4); glTexture.bind(); - GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MIN_FILTER, GL13.GL_LINEAR); - GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MAG_FILTER, GL13.GL_LINEAR); - GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_S, GL20.GL_MIRRORED_REPEAT); - GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_R, GL20.GL_MIRRORED_REPEAT); - GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_T, GL20.GL_MIRRORED_REPEAT); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_MIRRORED_REPEAT); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); uploadTexture(); } private void uploadTexture() { if (bufferDirty) { - GL20.glPixelStorei(GL20.GL_UNPACK_ROW_LENGTH, 0); - GL20.glPixelStorei(GL20.GL_UNPACK_SKIP_PIXELS, 0); - GL20.glPixelStorei(GL20.GL_UNPACK_SKIP_ROWS, 0); - GL20.glPixelStorei(GL20.GL_UNPACK_SKIP_IMAGES, 0); - GL20.glPixelStorei(GL20.GL_UNPACK_IMAGE_HEIGHT, 0); - GL20.glPixelStorei(GL20.GL_UNPACK_ALIGNMENT, 2); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 2); int sizeX = textureVolume.sizeX(); int sizeY = textureVolume.sizeY(); int sizeZ = textureVolume.sizeZ(); - GL12.glTexSubImage3D(GL12.GL_TEXTURE_3D, 0, 0, 0, 0, sizeX, sizeY, sizeZ, pixelFormat.format(), GL20.GL_UNSIGNED_BYTE, lightData); + glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, sizeX, sizeY, sizeZ, pixelFormat.format(), GL_UNSIGNED_BYTE, lightData); - GL20.glPixelStorei(GL20.GL_UNPACK_ALIGNMENT, 4); // 4 is the default + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4 is the default bufferDirty = false; } } @@ -278,11 +296,9 @@ public class LightVolume { public void delete() { removed = true; - RenderWork.enqueue(() -> { - glTexture.delete(); - MemoryUtil.memFree(lightData); - lightData = null; - }); + glTexture.delete(); + MemoryUtil.memFree(lightData); + lightData = null; } private void writeLight(int x, int y, int z, int block, int sky) { diff --git a/src/main/java/com/simibubi/create/CreateClient.java b/src/main/java/com/simibubi/create/CreateClient.java index 9b4106120..da0fab384 100644 --- a/src/main/java/com/simibubi/create/CreateClient.java +++ b/src/main/java/com/simibubi/create/CreateClient.java @@ -5,11 +5,7 @@ import java.util.List; import java.util.Map; import java.util.function.Function; -import javax.annotation.Nullable; - import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.OptifineHandler; -import com.jozufozu.flywheel.backend.instancing.TileInstanceManager; import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; @@ -52,7 +48,6 @@ import net.minecraft.util.text.TextComponentUtils; import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.event.ClickEvent; import net.minecraft.util.text.event.HoverEvent; -import net.minecraft.world.IWorld; import net.minecraftforge.client.event.ModelBakeEvent; import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.client.event.TextureStitchEvent; @@ -86,7 +81,6 @@ public class CreateClient { Backend.init(); CreateFlywheelHandler.init(); - OptifineHandler.init(); } public static void clientInit(FMLClientSetupEvent event) { @@ -207,19 +201,8 @@ public class CreateClient { } public static void invalidateRenderers() { - invalidateRenderers(null); - } - - public static void invalidateRenderers(@Nullable IWorld world) { BUFFER_CACHE.invalidate(); - if (world != null) { - Backend.tileInstanceManager.get(world) - .invalidate(); - } else { - Backend.tileInstanceManager.forEach(TileInstanceManager::invalidate); - } - ContraptionRenderDispatcher.invalidateAll(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java index c110a2836..ae2c21aca 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java @@ -7,8 +7,8 @@ import java.util.List; import javax.annotation.Nullable; -import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.KineticNetwork; import com.simibubi.create.content.contraptions.RotationPropagator; @@ -258,7 +258,7 @@ public abstract class KineticTileEntity extends SmartTileEntity effects.triggerOverStressedEffect(); if (clientPacket) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> Backend.enqueueUpdate(this)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); } public float getGeneratedSpeed() { @@ -557,7 +557,7 @@ public abstract class KineticTileEntity extends SmartTileEntity public void requestModelDataUpdate() { super.requestModelDataUpdate(); if (!this.removed) { - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> Backend.enqueueUpdate(this)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java index 1b6da372e..7282a1183 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java @@ -2,8 +2,8 @@ package com.simibubi.create.content.contraptions.components.structureMovement.ch import java.util.List; -import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; @@ -70,7 +70,7 @@ public class StickerTileEntity extends SmartTileEntity implements IInstanceRende DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> playSound(false)); piston.chase(target, .4f, Chaser.LINEAR); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> Backend.enqueueUpdate(this)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); } public boolean isAttachedToBlock() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java index 649966d05..54a768860 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java @@ -40,9 +40,9 @@ public class ContraptionInstanceManager extends TileInstanceManager { } @Override - protected boolean shouldTick(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) { - return true; - } + protected boolean shouldFrameUpdate(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) { + return true; + } @Nullable public ActorInstance createActor(Pair actor) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java index c27a3ca48..c21d61182 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java @@ -18,6 +18,9 @@ import org.apache.commons.lang3.tuple.Pair; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.loading.ModelTemplate; import com.jozufozu.flywheel.core.WorldContext; +import com.jozufozu.flywheel.event.BeginFrameEvent; +import com.jozufozu.flywheel.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.event.RenderLayerEvent; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.CreateClient; @@ -42,7 +45,6 @@ import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.BlockModelRenderer; import net.minecraft.client.renderer.BlockModelShapes; import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.RenderType; @@ -50,17 +52,18 @@ import net.minecraft.client.renderer.RenderTypeLookup; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.client.world.ClientWorld; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.world.LightType; import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template; import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.client.model.data.EmptyModelData; import net.minecraftforge.common.util.Lazy; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +@Mod.EventBusSubscriber public class ContraptionRenderDispatcher { private static final Lazy MODEL_RENDERER = Lazy.of(() -> new BlockModelRenderer(Minecraft.getInstance().getBlockColors())); private static final Lazy BLOCK_MODELS = Lazy.of(() -> Minecraft.getInstance().getModelManager().getBlockModelShapes()); @@ -92,7 +95,9 @@ public class ContraptionRenderDispatcher { } } - public static void beginFrame(ClientWorld world, MatrixStack stack, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture) { + @SubscribeEvent + public static void beginFrame(BeginFrameEvent event) { + ActiveRenderInfo info = event.getInfo(); double camX = info.getProjectedView().x; double camY = info.getProjectedView().y; double camZ = info.getProjectedView().z; @@ -101,10 +106,12 @@ public class ContraptionRenderDispatcher { } } - public static void renderLayer(ClientWorld world, RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) { + @SubscribeEvent + public static void renderLayer(RenderLayerEvent event) { removeDeadContraptions(); if (RENDERERS.isEmpty()) return; + RenderType layer = event.getType(); layer.startDrawing(); glEnable(GL_TEXTURE_3D); @@ -114,8 +121,8 @@ public class ContraptionRenderDispatcher { ContraptionProgram structureShader = STRUCTURE.getProgram(AllProgramSpecs.STRUCTURE); structureShader.bind(); - structureShader.uploadViewProjection(viewProjection); - structureShader.uploadCameraPos(camX, camY, camZ); + structureShader.uploadViewProjection(event.viewProjection); + structureShader.uploadCameraPos(event.camX, event.camY, event.camZ); for (RenderedContraption renderer : RENDERERS.values()) { renderer.doRenderLayer(layer, structureShader); @@ -124,7 +131,7 @@ public class ContraptionRenderDispatcher { if (Backend.canUseInstancing()) { for (RenderedContraption renderer : RENDERERS.values()) { - renderer.materialManager.render(layer, viewProjection, camX, camY, camZ, renderer::setup); + renderer.materialManager.render(layer, event.viewProjection, event.camX, event.camY, event.camZ, renderer::setup); } } @@ -134,6 +141,11 @@ public class ContraptionRenderDispatcher { glActiveTexture(GL_TEXTURE0); } + @SubscribeEvent + public static void onRendererReload(ReloadRenderersEvent event) { + invalidateAll(); + } + public static void render(AbstractContraptionEntity entity, Contraption contraption, ContraptionMatrices matrices, IRenderTypeBuffer buffers) { World world = entity.world; @@ -157,7 +169,7 @@ public class ContraptionRenderDispatcher { if (contraption == null) { PlacementSimulationWorld renderWorld = setupRenderWorld(world, c); - contraption = new RenderedContraption(world, renderWorld, c); + contraption = new RenderedContraption(renderWorld, c); RENDERERS.put(entityId, contraption); } @@ -183,7 +195,7 @@ public class ContraptionRenderDispatcher { renderWorld.setTileEntities(c.presentTileEntities.values()); for (Template.BlockInfo info : c.getBlocks() - .values()) + .values()) // Skip individual lighting updates to prevent lag with large contraptions renderWorld.setBlockState(info.pos, info.state, 128); @@ -220,7 +232,7 @@ public class ContraptionRenderDispatcher { MatrixStack m = matrices.contraptionStack; m.push(); MatrixStacker.of(m) - .translate(blockInfo.pos); + .translate(blockInfo.pos); MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); if (movementBehaviour != null) @@ -264,7 +276,7 @@ public class ContraptionRenderDispatcher { ForgeHooksClient.setRenderLayer(layer); BlockModelRenderer.enableCache(); for (Template.BlockInfo info : c.getBlocks() - .values()) { + .values()) { BlockState state = info.state; if (state.getRenderType() != BlockRenderType.MODEL) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java index 6b5b8fbb2..ea2fbeeb3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java @@ -58,7 +58,7 @@ public class RenderedContraption extends ContraptionWorldHolder { private Matrix4f model; private AxisAlignedBB lightBox; - public RenderedContraption(World world, PlacementSimulationWorld renderWorld, Contraption contraption) { + public RenderedContraption(PlacementSimulationWorld renderWorld, Contraption contraption) { super(contraption, renderWorld); this.lighter = contraption.makeLighter(); this.materialManager = new ContraptionMaterialManager(ContraptionRenderDispatcher.TILES); @@ -119,6 +119,7 @@ public class RenderedContraption extends ContraptionWorldHolder { lighter.lightVolume.delete(); + materialManager.delete(); kinetics.invalidate(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java index 76e4755e1..5beca0399 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java @@ -12,7 +12,7 @@ import java.util.Map; import java.util.Optional; import java.util.function.Function; -import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.light.GridAlignedBB; import com.jozufozu.flywheel.light.ILightUpdateListener; import com.jozufozu.flywheel.light.LightUpdater; @@ -267,7 +267,7 @@ public class BeltTileEntity extends KineticTileEntity implements ILightUpdateLis belt.color = Optional.ofNullable(colorIn); belt.markDirty(); belt.sendData(); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> Backend.enqueueUpdate(belt)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(belt)); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java index b206b0cbc..7ac0d540c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java @@ -9,8 +9,8 @@ import java.util.Set; import org.apache.commons.lang3.tuple.Pair; -import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock.Shape; import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock; @@ -103,7 +103,7 @@ public class BeltTunnelTileEntity extends SmartTileEntity implements IInstanceRe sides.addAll(flaps.keySet()); super.fromTag(state, compound, clientPacket); if (clientPacket) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> Backend.enqueueUpdate(this)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); } public void updateTunnelConnections() { diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java index 47e3bff94..116d74468 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java @@ -3,8 +3,8 @@ package com.simibubi.create.content.logistics.block.funnel; import java.lang.ref.WeakReference; import java.util.List; -import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.goggles.IHaveHoveringInformation; @@ -327,7 +327,7 @@ public class FunnelTileEntity extends SmartTileEntity implements IHaveHoveringIn extractionCooldown = compound.getInt("TransferCooldown"); if (clientPacket) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> Backend.enqueueUpdate(this)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); } @Override diff --git a/src/main/java/com/simibubi/create/events/ClientEvents.java b/src/main/java/com/simibubi/create/events/ClientEvents.java index b969f60c9..6391be8a2 100644 --- a/src/main/java/com/simibubi/create/events/ClientEvents.java +++ b/src/main/java/com/simibubi/create/events/ClientEvents.java @@ -3,9 +3,7 @@ package com.simibubi.create.events; import java.util.ArrayList; import java.util.List; -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.RenderWork; -import com.jozufozu.flywheel.backend.instancing.TileInstanceManager; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.AllFluids; @@ -110,7 +108,7 @@ public class ClientEvents { SoundScapes.tick(); AnimationTickHolder.tick(); - Backend.tick(); + InstancedRenderDispatcher.tick(); ScrollValueHandler.tick(); CreateClient.SCHEMATIC_SENDER.tick(); @@ -154,11 +152,8 @@ public class ClientEvents { public static void onLoadWorld(WorldEvent.Load event) { IWorld world = event.getWorld(); if (world.isRemote() && world instanceof ClientWorld && !(world instanceof WrappedClientWorld)) { - CreateClient.invalidateRenderers(world); + CreateClient.invalidateRenderers(); AnimationTickHolder.reset(); - TileInstanceManager renderer = Backend.tileInstanceManager.get(world); - renderer.invalidate(); - ((ClientWorld) world).loadedTileEntityList.forEach(renderer::add); } /* @@ -173,7 +168,7 @@ public class ClientEvents { public static void onUnloadWorld(WorldEvent.Unload event) { if (event.getWorld() .isRemote()) { - CreateClient.invalidateRenderers(event.getWorld()); + CreateClient.invalidateRenderers(); AnimationTickHolder.reset(); } } @@ -199,8 +194,6 @@ public class ClientEvents { RenderSystem.enableCull(); ms.pop(); - - RenderWork.runAll(); } @SubscribeEvent diff --git a/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java b/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java index 540c4ffee..9785d19d8 100644 --- a/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java @@ -2,6 +2,7 @@ package com.simibubi.create.foundation.fluid; import java.util.function.Function; +import com.jozufozu.flywheel.event.RenderLayerEvent; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack.Entry; import com.mojang.blaze3d.vertex.IVertexBuilder; @@ -15,7 +16,6 @@ import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.world.ClientWorld; import net.minecraft.fluid.Fluid; import net.minecraft.inventory.container.PlayerContainer; import net.minecraft.util.Direction; @@ -23,12 +23,14 @@ import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3i; +import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fluids.FluidAttributes; import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fml.common.Mod; +@Mod.EventBusSubscriber public class FluidRenderer { // If we draw to BufferBuilder that minecraft provides for RenderType.getTranslucent(), minecraft draws the contents @@ -49,9 +51,10 @@ public class FluidRenderer { return _builder; } - public static void renderLayer(ClientWorld world, RenderType type, Matrix4f viewProjection, double camX, double camY, double camZ) { - if (type == RenderType.getTranslucent()) { - type.draw(_builder, 0, 0, 0); + @SubscribeEvent + public static void renderLayer(RenderLayerEvent event) { + if (event.type == RenderType.getTranslucent()) { + event.type.draw(_builder, 0, 0, 0); } } @@ -76,9 +79,9 @@ public class FluidRenderer { ms.push(); msr.centre() - .rotateY(AngleHelper.horizontalAngle(direction)) - .rotateX(direction == Direction.UP ? 0 : direction == Direction.DOWN ? 180 : 90) - .unCentre(); + .rotateY(AngleHelper.horizontalAngle(direction)) + .rotateX(direction == Direction.UP ? 0 : direction == Direction.DOWN ? 180 : 90) + .unCentre(); ms.translate(.5, 0, .5); float h = (float) (radius); @@ -91,21 +94,21 @@ public class FluidRenderer { for (int i = 0; i < 4; i++) { ms.push(); renderTiledHorizontalFace(h, Direction.SOUTH, hMin, yMin, hMax, yMax, builder, ms, light, color, - flowTexture); + flowTexture); ms.pop(); msr.rotateY(90); } if (progress != 1) renderTiledVerticalFace(yMax, Direction.UP, hMin, hMin, hMax, hMax, builder, ms, light, color, - stillTexture); + stillTexture); ms.pop(); } public static void renderTiledFluidBB(FluidStack fluidStack, float xMin, float yMin, float zMin, float xMax, - float yMax, float zMax, IRenderTypeBuffer buffer, MatrixStack ms, int light, boolean renderBottom) { + float yMax, float zMax, IRenderTypeBuffer buffer, MatrixStack ms, int light, boolean renderBottom) { Fluid fluid = fluidStack.getFluid(); FluidAttributes fluidAttributes = fluid.getAttributes(); TextureAtlasSprite fluidTexture = Minecraft.getInstance() @@ -124,18 +127,18 @@ public class FluidRenderer { ms.push(); if (fluidStack.getFluid() .getAttributes() - .isLighterThanAir()) + .isLighterThanAir()) MatrixStacker.of(ms) - .translate(center) - .rotateX(180) - .translateBack(center); + .translate(center) + .rotateX(180) + .translateBack(center); for (Direction side : Iterate.directions) { if (side == Direction.DOWN && !renderBottom) continue; if (side.getAxis() - .isHorizontal()) { + .isHorizontal()) { ms.push(); if (side.getAxisDirection() == AxisDirection.NEGATIVE) @@ -161,7 +164,7 @@ public class FluidRenderer { } private static void renderTiledVerticalFace(float y, Direction face, float xMin, float zMin, float xMax, float zMax, - IVertexBuilder builder, MatrixStack ms, int light, int color, TextureAtlasSprite texture) { + IVertexBuilder builder, MatrixStack ms, int light, int color, TextureAtlasSprite texture) { float x2 = 0; float z2 = 0; for (float x1 = xMin; x1 < xMax; x1 = x2) { @@ -183,7 +186,7 @@ public class FluidRenderer { } private static void renderTiledHorizontalFace(float h, Direction face, float hMin, float yMin, float hMax, - float yMax, IVertexBuilder builder, MatrixStack ms, int light, int color, TextureAtlasSprite texture) { + float yMax, IVertexBuilder builder, MatrixStack ms, int light, int color, TextureAtlasSprite texture) { boolean X = face.getAxis() == Axis.X; float h2 = 0; @@ -220,7 +223,7 @@ public class FluidRenderer { } private static void putVertex(IVertexBuilder builder, MatrixStack ms, float x, float y, float z, int color, float u, - float v, Direction face, int light) { + float v, Direction face, int light) { Vector3i n = face.getDirectionVec(); Entry peek = ms.peek(); @@ -231,11 +234,11 @@ public class FluidRenderer { int b = color & ff; builder.vertex(peek.getModel(), x, y, z) - .color(r, g, b, a) - .texture(u, v) - .light(light) - .normal(n.getX(), n.getY(), n.getZ()) - .endVertex(); + .color(r, g, b, a) + .texture(u, v) + .light(light) + .normal(n.getX(), n.getY(), n.getZ()) + .endVertex(); } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/RenderHooksMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/RenderHooksMixin.java index 39bfa9433..fa244b629 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/RenderHooksMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/RenderHooksMixin.java @@ -9,6 +9,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.OptifineHandler; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.event.BeginFrameEvent; +import com.jozufozu.flywheel.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.event.RenderLayerEvent; import com.mojang.blaze3d.matrix.MatrixStack; import net.minecraft.block.BlockState; @@ -23,6 +27,7 @@ import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Vector3d; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.MinecraftForge; @OnlyIn(Dist.CLIENT) @Mixin(WorldRenderer.class) @@ -35,7 +40,7 @@ public class RenderHooksMixin { private void setupFrame(MatrixStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f p_228426_9_, CallbackInfo ci) { - Backend.listeners.setupFrame(world, stack, info, gameRenderer, lightTexture); + MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(world, stack, info, gameRenderer, lightTexture)); } /** @@ -54,7 +59,7 @@ public class RenderHooksMixin { Matrix4f viewProjection = view.copy(); viewProjection.multiplyBackward(Backend.getProjectionMatrix()); - Backend.listeners.renderLayer(world, type, viewProjection, camX, camY, camZ); + MinecraftForge.EVENT_BUS.post(new RenderLayerEvent(world, type, viewProjection, camX, camY, camZ)); GL20.glUseProgram(0); } @@ -63,7 +68,7 @@ public class RenderHooksMixin { OptifineHandler.refresh(); Backend.refresh(); - Backend.listeners.refresh(world); + MinecraftForge.EVENT_BUS.post(new ReloadRenderersEvent(world)); } @@ -86,7 +91,7 @@ public class RenderHooksMixin { viewProjection.multiplyBackward(Backend.getProjectionMatrix()); Vector3d cameraPos = info.getProjectedView(); - Backend.renderBreaking(world, viewProjection, cameraPos.x, cameraPos.y, cameraPos.z); + InstancedRenderDispatcher.renderBreaking(world, viewProjection, cameraPos.x, cameraPos.y, cameraPos.z); GL20.glUseProgram(0); } @@ -94,7 +99,7 @@ public class RenderHooksMixin { @Inject(at = @At("TAIL"), method = "scheduleBlockRerenderIfNeeded") private void checkUpdate(BlockPos pos, BlockState lastState, BlockState newState, CallbackInfo ci) { - Backend.tileInstanceManager.get(world) + InstancedRenderDispatcher.get(world) .update(world.getTileEntity(pos)); } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileRemoveMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileRemoveMixin.java index bf5d14abf..b433bd3be 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileRemoveMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileRemoveMixin.java @@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import net.minecraft.client.world.ClientWorld; import net.minecraft.tileentity.TileEntity; @@ -24,7 +24,7 @@ public class TileRemoveMixin { @Inject(at = @At("TAIL"), method = "remove") private void onRemove(CallbackInfo ci) { if (world instanceof ClientWorld) - Backend.tileInstanceManager.get(this.world) + InstancedRenderDispatcher.get(this.world) .remove((TileEntity) (Object) this); } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileWorldHookMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileWorldHookMixin.java index 0ec98abcc..0b622ae58 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileWorldHookMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileWorldHookMixin.java @@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.TileInstanceManager; import net.minecraft.tileentity.TileEntity; @@ -35,7 +35,7 @@ public class TileWorldHookMixin { @Inject(at = @At("TAIL"), method = "addTileEntity") private void onAddTile(TileEntity te, CallbackInfoReturnable cir) { if (isRemote) { - Backend.tileInstanceManager.get(self) + InstancedRenderDispatcher.get(self) .queueAdd(te); } } @@ -46,7 +46,7 @@ public class TileWorldHookMixin { @Inject(at = @At(value = "INVOKE", target = "Ljava/util/Set;clear()V", ordinal = 0), method = "tickBlockEntities") private void onChunkUnload(CallbackInfo ci) { if (isRemote) { - TileInstanceManager kineticRenderer = Backend.tileInstanceManager.get(self); + TileInstanceManager kineticRenderer = InstancedRenderDispatcher.get(self); for (TileEntity tile : tileEntitiesToBeRemoved) { kineticRenderer.remove(tile); } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/LightUpdateMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/LightUpdateMixin.java index 1f8b0b6ef..bbd9c970e 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/LightUpdateMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/LightUpdateMixin.java @@ -7,7 +7,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.light.LightUpdater; import net.minecraft.client.multiplayer.ClientChunkProvider; @@ -46,7 +46,7 @@ public abstract class LightUpdateMixin extends AbstractChunkProvider { .getY()) == sectionY) .map(Map.Entry::getValue) .forEach(tile -> { - Backend.tileInstanceManager.get(world) + InstancedRenderDispatcher.get(world) .onLightUpdate(tile); }); } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/NetworkLightUpdateMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/NetworkLightUpdateMixin.java index bccbe7822..fc8f6fb08 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/NetworkLightUpdateMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/NetworkLightUpdateMixin.java @@ -5,8 +5,8 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.RenderWork; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.light.LightUpdater; import net.minecraft.client.Minecraft; @@ -36,7 +36,7 @@ public class NetworkLightUpdateMixin { chunk.getTileEntityMap() .values() .forEach(tile -> { - Backend.tileInstanceManager.get(world) + InstancedRenderDispatcher.get(world) .onLightUpdate(tile); }); } diff --git a/src/main/java/com/simibubi/create/foundation/render/CreateFlywheelHandler.java b/src/main/java/com/simibubi/create/foundation/render/CreateFlywheelHandler.java index 7dc49abdf..0a7a950f0 100644 --- a/src/main/java/com/simibubi/create/foundation/render/CreateFlywheelHandler.java +++ b/src/main/java/com/simibubi/create/foundation/render/CreateFlywheelHandler.java @@ -2,7 +2,6 @@ package com.simibubi.create.foundation.render; import com.jozufozu.flywheel.backend.Backend; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.fluid.FluidRenderer; import com.simibubi.create.foundation.render.effects.EffectsContext; public class CreateFlywheelHandler { @@ -10,9 +9,5 @@ public class CreateFlywheelHandler { Backend.register(ContraptionRenderDispatcher.TILES); Backend.register(ContraptionRenderDispatcher.STRUCTURE); Backend.register(EffectsContext.INSTANCE); - Backend.listeners.renderLayerListener(ContraptionRenderDispatcher::renderLayer); - Backend.listeners.renderLayerListener(FluidRenderer::renderLayer); - Backend.listeners.setupFrameListener(ContraptionRenderDispatcher::beginFrame); - Backend.listeners.refreshListener($ -> ContraptionRenderDispatcher.invalidateAll()); } } diff --git a/src/main/java/com/simibubi/create/foundation/render/effects/EffectsContext.java b/src/main/java/com/simibubi/create/foundation/render/effects/EffectsContext.java index 6f42dbd43..cdea1bc2a 100644 --- a/src/main/java/com/simibubi/create/foundation/render/effects/EffectsContext.java +++ b/src/main/java/com/simibubi/create/foundation/render/effects/EffectsContext.java @@ -4,7 +4,8 @@ import java.util.Collections; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.ShaderContext; -import com.jozufozu.flywheel.backend.ShaderLoader; +import com.jozufozu.flywheel.backend.ShaderSources; +import com.jozufozu.flywheel.backend.loading.Shader; import com.jozufozu.flywheel.backend.loading.ShaderTransformer; import com.jozufozu.flywheel.core.shader.IMultiProgram; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; @@ -19,14 +20,14 @@ public class EffectsContext extends ShaderContext { } @Override - protected IMultiProgram loadSpecInternal(ShaderLoader loader, ProgramSpec spec) { + protected IMultiProgram loadSpecInternal(ShaderSources loader, ProgramSpec spec) { return new SphereFilterProgram(loadProgram(loader, spec, Collections.emptyList())); } @Override - public void load(ShaderLoader loader) { + public void load(ShaderSources loader) { transformer = new ShaderTransformer() - .pushStage(loader::processIncludes); + .pushStage(Shader::processIncludes); loadProgramFromSpec(loader, Backend.getSpec(AllProgramSpecs.CHROMATIC)); } }