Event system, sort of untangle backend

This commit is contained in:
JozsefA 2021-06-04 15:56:46 -07:00
parent bef6d77a59
commit 9bac709dfd
39 changed files with 541 additions and 414 deletions

View file

@ -1,19 +1,10 @@
package com.jozufozu.flywheel.backend; 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.ArrayList;
import java.util.BitSet;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.SortedSet;
import java.util.Vector;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; 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.shader.GlProgram;
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
import com.jozufozu.flywheel.backend.instancing.InstanceData; 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.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.WorldContext;
import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
import com.jozufozu.flywheel.util.WorldAttached;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import net.minecraft.client.Minecraft; 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.IReloadableResourceManager;
import net.minecraft.resources.IResourceManager; import net.minecraft.resources.IResourceManager;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.LazyValue;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
public class Backend { public class Backend {
public static final Logger log = LogManager.getLogger(Backend.class); public static final Logger log = LogManager.getLogger(Backend.class);
public static final ShaderLoader shaderLoader = new ShaderLoader(); public static final ShaderSources SHADER_SOURCES = new ShaderSources();
public static final FlywheelListeners listeners = new FlywheelListeners();
public static GLCapabilities capabilities; public static GLCapabilities capabilities;
public static GlCompat compat; public static GlCompat compat;
public static WorldAttached<TileInstanceManager> tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(WorldContext.INSTANCE.getMaterialManager(world)));
public static LazyValue<Vector<CrumblingInstanceManager>> blockBreaking = new LazyValue<>(() -> {
Vector<CrumblingInstanceManager> 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 Matrix4f projectionMatrix = new Matrix4f();
private static boolean instancedArrays; private static boolean instancedArrays;
private static boolean enabled; private static boolean enabled;
@ -84,26 +46,6 @@ public class Backend {
static { static {
register(WorldContext.INSTANCE); register(WorldContext.INSTANCE);
register(WorldContext.CRUMBLING); 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() { public Backend() {
@ -165,7 +107,7 @@ public class Backend {
/** /**
* Used to avoid calling Flywheel functions on (fake) worlds that don't specifically support it. * 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; return (world instanceof IFlywheelWorld && ((IFlywheelWorld) world).supportsFlywheel()) || world == Minecraft.getInstance().world;
} }
@ -197,8 +139,10 @@ public class Backend {
IResourceManager manager = mc.getResourceManager(); IResourceManager manager = mc.getResourceManager();
if (manager instanceof IReloadableResourceManager) { if (manager instanceof IReloadableResourceManager) {
((IReloadableResourceManager) manager).addReloadListener(shaderLoader); ((IReloadableResourceManager) manager).addReloadListener(SHADER_SOURCES);
} }
OptifineHandler.init();
} }
public static void refresh() { public static void refresh() {
@ -213,84 +157,6 @@ public class Backend {
enabled = AllConfigs.CLIENT.experimentalRendering.get() && !OptifineHandler.usingShaders(); 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<WorldProgram> 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<SortedSet<DestroyBlockProgress>> breakingProgressions = worldRenderer.blockBreakingProgressions;
if (breakingProgressions.isEmpty()) return;
Vector<CrumblingInstanceManager> renderers = blockBreaking.getValue();
BitSet bitSet = new BitSet(10);
for (Long2ObjectMap.Entry<SortedSet<DestroyBlockProgress>> entry : breakingProgressions.long2ObjectEntrySet()) {
BlockPos breakingPos = BlockPos.fromLong(entry.getLongKey());
SortedSet<DestroyBlockProgress> 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() { public static void reloadWorldRenderers() {
RenderWork.enqueue(Minecraft.getInstance().worldRenderer::loadRenderers); RenderWork.enqueue(Minecraft.getInstance().worldRenderer::loadRenderers);
} }

View file

@ -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<SetupFrame> setupFrameListeners = new ArrayList<>();
private final List<RenderLayer> renderLayerListeners = new ArrayList<>();
private final List<Refresh> 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);
}
}

View file

@ -3,10 +3,18 @@ package com.jozufozu.flywheel.backend;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue; 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 { public class RenderWork {
private static final Queue<Runnable> runs = new ConcurrentLinkedQueue<>(); private static final Queue<Runnable> runs = new ConcurrentLinkedQueue<>();
public static void runAll() {
@SubscribeEvent(priority = EventPriority.LOWEST)
public static void onRenderWorldLast(RenderWorldLastEvent event) {
while (!runs.isEmpty()) { while (!runs.isEmpty()) {
runs.remove().run(); runs.remove().run();
} }

View file

@ -20,18 +20,19 @@ public abstract class ShaderContext<P extends GlProgram> {
protected ShaderTransformer transformer = new ShaderTransformer(); protected ShaderTransformer transformer = new ShaderTransformer();
public ShaderContext() { } public ShaderContext() {
}
// TODO: Untangle the loading functions // TODO: Untangle the loading functions
/** /**
* Load all programs associated with this context. This might be just one, if the context is very specialized. * 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<P> loadSpecInternal(ShaderLoader loader, ProgramSpec spec); protected abstract IMultiProgram<P> loadSpecInternal(ShaderSources loader, ProgramSpec spec);
public void loadProgramFromSpec(ShaderLoader loader, ProgramSpec programSpec) { public void loadProgramFromSpec(ShaderSources loader, ProgramSpec programSpec) {
try { try {
programs.put(programSpec.name, loadSpecInternal(loader, programSpec)); programs.put(programSpec.name, loadSpecInternal(loader, programSpec));
@ -43,7 +44,7 @@ public abstract class ShaderContext<P extends GlProgram> {
} }
} }
public Program loadProgram(ShaderLoader loader, ProgramSpec spec, Collection<String> defines) { public Program loadProgram(ShaderSources loader, ProgramSpec spec, Collection<String> defines) {
Shader vertexFile = loader.source(spec.vert, ShaderType.VERTEX); Shader vertexFile = loader.source(spec.vert, ShaderType.VERTEX);
Shader fragmentFile = loader.source(spec.frag, ShaderType.FRAGMENT); Shader fragmentFile = loader.source(spec.frag, ShaderType.FRAGMENT);

View file

@ -12,14 +12,9 @@ import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.function.Predicate; 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 java.util.stream.Stream;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -52,14 +47,11 @@ import net.minecraftforge.resource.ISelectiveResourceReloadListener;
import net.minecraftforge.resource.VanillaResourceType; import net.minecraftforge.resource.VanillaResourceType;
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public class ShaderLoader implements ISelectiveResourceReloadListener { public class ShaderSources implements ISelectiveResourceReloadListener {
public static final String SHADER_DIR = "flywheel/shaders/"; public static final String SHADER_DIR = "flywheel/shaders/";
public static final String PROGRAM_DIR = "flywheel/programs/"; public static final String PROGRAM_DIR = "flywheel/programs/";
public static final ArrayList<String> EXTENSIONS = Lists.newArrayList(".vert", ".vsh", ".frag", ".fsh", ".glsl"); public static final ArrayList<String> 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<ResourceLocation, String> shaderSource = new HashMap<>(); private final Map<ResourceLocation, String> shaderSource = new HashMap<>();
private boolean shouldCrash; private boolean shouldCrash;
@ -161,7 +153,7 @@ public class ShaderLoader implements ISelectiveResourceReloadListener {
} }
public Shader source(ResourceLocation name, ShaderType type) { 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) { public Program loadProgram(ResourceLocation name, Shader... shaders) {
@ -201,38 +193,6 @@ public class ShaderLoader implements ISelectiveResourceReloadListener {
} }
} }
public void processIncludes(Shader shader) {
HashSet<ResourceLocation> seen = new HashSet<>();
seen.add(shader.name);
String includesInjected = includeRecursive(shader.getSource(), seen).collect(Collectors.joining("\n"));
shader.setSource(includesInjected);
}
private Stream<String> includeRecursive(String source, Set<ResourceLocation> 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<String> lines(String s) { public static Stream<String> lines(String s) {
return new BufferedReader(new StringReader(s)).lines(); return new BufferedReader(new StringReader(s)).lines();
} }

View file

@ -49,8 +49,8 @@ public class InstanceMaterial<D extends InstanceData> {
this.models = CacheBuilder.newBuilder() this.models = CacheBuilder.newBuilder()
.removalListener(notification -> { .removalListener(notification -> {
Instancer<?> model = (Instancer<?>) notification.getValue(); Instancer<?> instancer = (Instancer<?>) notification.getValue();
RenderWork.enqueue(model::delete); RenderWork.enqueue(instancer::delete);
}) })
.build(); .build();
modelFormat = this.spec.getModelFormat(); modelFormat = this.spec.getModelFormat();

View file

@ -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> tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(WorldContext.INSTANCE.getMaterialManager(world)));
public static LazyValue<Vector<CrumblingInstanceManager>> blockBreaking = new LazyValue<>(() -> {
Vector<CrumblingInstanceManager> 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<WorldProgram> 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<SortedSet<DestroyBlockProgress>> breakingProgressions = worldRenderer.blockBreakingProgressions;
if (breakingProgressions.isEmpty()) return;
Vector<CrumblingInstanceManager> renderers = blockBreaking.getValue();
BitSet bitSet = new BitSet(10);
for (Long2ObjectMap.Entry<SortedSet<DestroyBlockProgress>> entry : breakingProgressions.long2ObjectEntrySet()) {
BlockPos breakingPos = BlockPos.fromLong(entry.getLongKey());
SortedSet<DestroyBlockProgress> 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());
}
}

View file

@ -9,6 +9,7 @@ import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -24,8 +25,8 @@ public class TileInstanceManager implements MaterialManager.OriginShiftListener
protected final ConcurrentHashMap.KeySetView<TileEntity, Boolean> queuedUpdates; protected final ConcurrentHashMap.KeySetView<TileEntity, Boolean> queuedUpdates;
protected final Map<TileEntity, TileEntityInstance<?>> instances; protected final Map<TileEntity, TileEntityInstance<?>> instances;
protected final Map<TileEntity, ITickableInstance> tickableInstances; protected final Object2ObjectOpenHashMap<TileEntity, ITickableInstance> tickableInstances;
protected final Map<TileEntity, IDynamicInstance> dynamicInstances; protected final Object2ObjectOpenHashMap<TileEntity, IDynamicInstance> dynamicInstances;
protected int frame; protected int frame;
protected int tick; protected int tick;
@ -34,10 +35,11 @@ public class TileInstanceManager implements MaterialManager.OriginShiftListener
this.materialManager = materialManager; this.materialManager = materialManager;
this.queuedUpdates = ConcurrentHashMap.newKeySet(64); this.queuedUpdates = ConcurrentHashMap.newKeySet(64);
this.queuedAdditions = new ArrayList<>(64); this.queuedAdditions = new ArrayList<>(64);
this.dynamicInstances = new HashMap<>();
this.tickableInstances = new HashMap<>();
this.instances = new HashMap<>(); this.instances = new HashMap<>();
this.dynamicInstances = new Object2ObjectOpenHashMap<>();
this.tickableInstances = new Object2ObjectOpenHashMap<>();
materialManager.onOriginShift(this); materialManager.onOriginShift(this);
} }
@ -89,10 +91,11 @@ public class TileInstanceManager implements MaterialManager.OriginShiftListener
int cZ = (int) info.getProjectedView().z; int cZ = (int) info.getProjectedView().z;
if (dynamicInstances.size() > 0) { if (dynamicInstances.size() > 0) {
for (IDynamicInstance dyn : dynamicInstances.values()) { dynamicInstances.object2ObjectEntrySet().fastForEach(e -> {
if (!dyn.decreaseFramerateWithDistance() || shouldTick(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ)) IDynamicInstance dyn = e.getValue();
if (!dyn.decreaseFramerateWithDistance() || shouldFrameUpdate(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ))
dyn.beginFrame(); 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 dX = worldPos.getX() - cX;
int dY = worldPos.getY() - cY; int dY = worldPos.getY() - cY;
int dZ = worldPos.getZ() - cZ; int dZ = worldPos.getZ() - cZ;
float dot = (dX + lookX * 2) * lookX + (dY + lookY * 2) * lookY + (dZ + lookZ * 2) * lookZ; // is it more than 2 blocks behind the camera?
int dist = 2;
if (dot < 0) return false; // is it more than 2 blocks behind the camera? 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; return (frame % getUpdateDivisor(dX, dY, dZ)) == 0;
} }

View file

@ -1,7 +1,7 @@
package com.jozufozu.flywheel.backend.loading; package com.jozufozu.flywheel.backend.loading;
import com.jozufozu.flywheel.Flywheel; 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 com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import net.minecraft.util.ResourceLocation; 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 vert = new ResourceLocation(Flywheel.ID, "template/instanced/instanced.vert");
public static final ResourceLocation frag = new ResourceLocation(Flywheel.ID, "template/instanced/instanced.frag"); public static final ResourceLocation frag = new ResourceLocation(Flywheel.ID, "template/instanced/instanced.frag");
public InstancedArraysTemplate(ShaderLoader loader) { public InstancedArraysTemplate(ShaderSources loader) {
super(loader); super(loader);
templates.put(ShaderType.VERTEX, new ShaderTemplate(requiredVert, loader.getShaderSource(vert))); templates.put(ShaderType.VERTEX, new ShaderTemplate(requiredVert, loader.getShaderSource(vert)));

View file

@ -1,7 +1,7 @@
package com.jozufozu.flywheel.backend.loading; package com.jozufozu.flywheel.backend.loading;
import com.jozufozu.flywheel.Flywheel; 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 com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import net.minecraft.util.ResourceLocation; 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 vert = new ResourceLocation(Flywheel.ID, "template/model/model.vert");
public static final ResourceLocation frag = new ResourceLocation(Flywheel.ID, "template/model/model.frag"); public static final ResourceLocation frag = new ResourceLocation(Flywheel.ID, "template/model/model.frag");
public ModelTemplate(ShaderLoader loader) { public ModelTemplate(ShaderSources loader) {
super(loader); super(loader);
templates.put(ShaderType.VERTEX, new ShaderTemplate(requiredVert, loader.getShaderSource(vert))); templates.put(ShaderType.VERTEX, new ShaderTemplate(requiredVert, loader.getShaderSource(vert)));

View file

@ -3,15 +3,15 @@ package com.jozufozu.flywheel.backend.loading;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.Map; import java.util.Map;
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.gl.shader.ShaderType;
public abstract class ProgramTemplate implements IProcessingStage { public abstract class ProgramTemplate implements IProcessingStage {
protected final ShaderLoader loader; protected final ShaderSources loader;
protected Map<ShaderType, ShaderTemplate> templates = new EnumMap<>(ShaderType.class); protected Map<ShaderType, ShaderTemplate> templates = new EnumMap<>(ShaderType.class);
public ProgramTemplate(ShaderLoader loader) { public ProgramTemplate(ShaderSources loader) {
this.loader = loader; this.loader = loader;
} }

View file

@ -1,32 +1,43 @@
package com.jozufozu.flywheel.backend.loading; package com.jozufozu.flywheel.backend.loading;
import java.io.BufferedReader;
import java.io.StringReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; 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 com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
public class Shader { 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]*"); public static final Pattern versionDetector = Pattern.compile("#version[^\\n]*");
private static final Pattern decorator = Pattern.compile("#\\[([\\w_]*)]"); private static final Pattern decorator = Pattern.compile("#\\[([\\w_]*)]");
public final ResourceLocation name; public final ResourceLocation name;
public ShaderType type; public ShaderType type;
private String source; private String source;
private final ShaderSources loader;
private boolean parsed = false; private boolean parsed = false;
final List<TaggedStruct> structs = new ArrayList<>(3); final List<TaggedStruct> structs = new ArrayList<>(3);
final Map<String, TaggedStruct> tag2Struct = new HashMap<>(); final Map<String, TaggedStruct> tag2Struct = new HashMap<>();
final Map<String, TaggedStruct> name2Struct = new HashMap<>(); final Map<String, TaggedStruct> 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.type = type;
this.name = name; this.name = name;
this.source = source; this.source = source;
@ -91,4 +102,39 @@ public class Shader {
this.source = strippedSrc.toString(); this.source = strippedSrc.toString();
} }
public void processIncludes() {
HashSet<ResourceLocation> seen = new HashSet<>();
seen.add(name);
source = includeRecursive(source, seen).collect(Collectors.joining("\n"));
}
private Stream<String> includeRecursive(String source, Set<ResourceLocation> 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<String> lines(String s) {
return new BufferedReader(new StringReader(s)).lines();
}
} }

View file

@ -11,7 +11,7 @@ public class CrumblingInstanceManager extends TileInstanceManager {
} }
@Override @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; return true;
} }
} }

View file

@ -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.GlBuffer;
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.backend.model.ElementBuffer; 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. * A class to manage EBOs that index quads as triangles.
*/ */
@Mod.EventBusSubscriber
public class QuadConverter { public class QuadConverter {
public static final int STARTING_CAPACITY = 42; public static final int STARTING_CAPACITY = 42;
@ -158,4 +164,10 @@ public class QuadConverter {
return GlNumericType.UINT; 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();
}
} }

View file

@ -11,7 +11,7 @@ import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.ResourceUtil; import com.jozufozu.flywheel.backend.ResourceUtil;
import com.jozufozu.flywheel.backend.ShaderContext; 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.gl.shader.ShaderType;
import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.jozufozu.flywheel.backend.instancing.MaterialManager;
import com.jozufozu.flywheel.backend.instancing.MaterialSpec; import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
@ -43,7 +43,7 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
protected Supplier<Stream<ResourceLocation>> specStream; protected Supplier<Stream<ResourceLocation>> specStream;
protected TemplateFactory templateFactory; protected TemplateFactory templateFactory;
public final WorldAttached<MaterialManager<P>> materialManager = new WorldAttached<>($ -> new MaterialManager<>(this)); private final WorldAttached<MaterialManager<P>> materialManager = new WorldAttached<>($ -> new MaterialManager<>(this));
private final Map<ShaderType, ResourceLocation> builtins = new EnumMap<>(ShaderType.class); private final Map<ShaderType, ResourceLocation> builtins = new EnumMap<>(ShaderType.class);
private final Map<ShaderType, String> builtinSources = new EnumMap<>(ShaderType.class); private final Map<ShaderType, String> builtinSources = new EnumMap<>(ShaderType.class);
@ -78,13 +78,14 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
} }
@Override @Override
protected IMultiProgram<P> loadSpecInternal(ShaderLoader loader, ProgramSpec spec) { protected IMultiProgram<P> loadSpecInternal(ShaderSources loader, ProgramSpec spec) {
return new StateSensitiveMultiProgram<>(loader, factory, this, spec); return new StateSensitiveMultiProgram<>(loader, factory, this, spec);
} }
protected ProgramTemplate template; protected ProgramTemplate template;
@Override @Override
public void load(ShaderLoader loader) { public void load(ShaderSources loader) {
programs.values().forEach(IMultiProgram::delete); programs.values().forEach(IMultiProgram::delete);
programs.clear(); programs.clear();
@ -103,10 +104,10 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
template = templateFactory.create(loader); template = templateFactory.create(loader);
transformer = new ShaderTransformer() transformer = new ShaderTransformer()
.pushStage(this::injectBuiltins) .pushStage(this::injectBuiltins)
.pushStage(loader::processIncludes) .pushStage(Shader::processIncludes)
.pushStage(Shader::parseStructs) .pushStage(Shader::parseStructs)
.pushStage(template) .pushStage(template)
.pushStage(loader::processIncludes); .pushStage(Shader::processIncludes);
specStream.get() specStream.get()
.map(Backend::getSpec) .map(Backend::getSpec)
@ -131,6 +132,6 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
} }
public interface TemplateFactory { public interface TemplateFactory {
ProgramTemplate create(ShaderLoader loader); ProgramTemplate create(ShaderSources loader);
} }
} }

View file

@ -5,7 +5,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.backend.ShaderContext; 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.gl.shader.GlProgram;
import com.jozufozu.flywheel.backend.loading.Program; import com.jozufozu.flywheel.backend.loading.Program;
import com.jozufozu.flywheel.core.shader.spec.IContextCondition; import com.jozufozu.flywheel.core.shader.spec.IContextCondition;
@ -18,7 +18,7 @@ public class StateSensitiveMultiProgram<P extends GlProgram> implements IMultiPr
List<Pair<IContextCondition, P>> variants; List<Pair<IContextCondition, P>> variants;
P fallback; P fallback;
public StateSensitiveMultiProgram(ShaderLoader loader, ExtensibleGlProgram.Factory<P> factory, ShaderContext<P> context, ProgramSpec p) { public StateSensitiveMultiProgram(ShaderSources loader, ExtensibleGlProgram.Factory<P> factory, ShaderContext<P> context, ProgramSpec p) {
variants = new ArrayList<>(p.states.size()); variants = new ArrayList<>(p.states.size());
for (ProgramState state : p.states) { for (ProgramState state : p.states) {

View file

@ -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;
}
}

View file

@ -3,9 +3,14 @@ package com.jozufozu.flywheel.event;
import java.util.ArrayList; import java.util.ArrayList;
import com.jozufozu.flywheel.backend.Backend; 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.Minecraft;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.world.IWorld;
import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; 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);
}
}
} }

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -1,15 +1,33 @@
package com.jozufozu.flywheel.light; 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 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 org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.backend.Backend; 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.GlTexture;
import com.jozufozu.flywheel.backend.gl.versioned.RGPixelFormat; import com.jozufozu.flywheel.backend.gl.versioned.RGPixelFormat;
@ -35,20 +53,20 @@ public class LightVolume {
pixelFormat = Backend.compat.pixelFormat; 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()); this.lightData = MemoryUtil.memAlloc(this.textureVolume.volume() * pixelFormat.byteCount());
// allocate space for the texture // allocate space for the texture
GL20.glActiveTexture(GL20.GL_TEXTURE4); glActiveTexture(GL_TEXTURE4);
glTexture.bind(); glTexture.bind();
int sizeX = textureVolume.sizeX(); int sizeX = textureVolume.sizeX();
int sizeY = textureVolume.sizeY(); int sizeY = textureVolume.sizeY();
int sizeZ = textureVolume.sizeZ(); 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(); glTexture.unbind();
GL20.glActiveTexture(GL20.GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
} }
private void setSampleVolume(GridAlignedBB sampleVolume) { 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. // just in case something goes wrong or we accidentally call this before this volume is properly disposed of.
if (lightData == null || removed) return; if (lightData == null || removed) return;
GL13.glActiveTexture(GL20.GL_TEXTURE4); glActiveTexture(GL_TEXTURE4);
glTexture.bind(); glTexture.bind();
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MIN_FILTER, GL13.GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MAG_FILTER, GL13.GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_S, GL20.GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_R, GL20.GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_MIRRORED_REPEAT);
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_T, GL20.GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
uploadTexture(); uploadTexture();
} }
private void uploadTexture() { private void uploadTexture() {
if (bufferDirty) { if (bufferDirty) {
GL20.glPixelStorei(GL20.GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
GL20.glPixelStorei(GL20.GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
GL20.glPixelStorei(GL20.GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
GL20.glPixelStorei(GL20.GL_UNPACK_SKIP_IMAGES, 0); glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
GL20.glPixelStorei(GL20.GL_UNPACK_IMAGE_HEIGHT, 0); glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
GL20.glPixelStorei(GL20.GL_UNPACK_ALIGNMENT, 2); glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
int sizeX = textureVolume.sizeX(); int sizeX = textureVolume.sizeX();
int sizeY = textureVolume.sizeY(); int sizeY = textureVolume.sizeY();
int sizeZ = textureVolume.sizeZ(); 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; bufferDirty = false;
} }
} }
@ -278,11 +296,9 @@ public class LightVolume {
public void delete() { public void delete() {
removed = true; removed = true;
RenderWork.enqueue(() -> { glTexture.delete();
glTexture.delete(); MemoryUtil.memFree(lightData);
MemoryUtil.memFree(lightData); lightData = null;
lightData = null;
});
} }
private void writeLight(int x, int y, int z, int block, int sky) { private void writeLight(int x, int y, int z, int block, int sky) {

View file

@ -5,11 +5,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.Backend; 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.jozufozu.flywheel.core.PartialModel;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; 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.TextFormatting;
import net.minecraft.util.text.event.ClickEvent; import net.minecraft.util.text.event.ClickEvent;
import net.minecraft.util.text.event.HoverEvent; import net.minecraft.util.text.event.HoverEvent;
import net.minecraft.world.IWorld;
import net.minecraftforge.client.event.ModelBakeEvent; import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.client.event.TextureStitchEvent;
@ -86,7 +81,6 @@ public class CreateClient {
Backend.init(); Backend.init();
CreateFlywheelHandler.init(); CreateFlywheelHandler.init();
OptifineHandler.init();
} }
public static void clientInit(FMLClientSetupEvent event) { public static void clientInit(FMLClientSetupEvent event) {
@ -207,19 +201,8 @@ public class CreateClient {
} }
public static void invalidateRenderers() { public static void invalidateRenderers() {
invalidateRenderers(null);
}
public static void invalidateRenderers(@Nullable IWorld world) {
BUFFER_CACHE.invalidate(); BUFFER_CACHE.invalidate();
if (world != null) {
Backend.tileInstanceManager.get(world)
.invalidate();
} else {
Backend.tileInstanceManager.forEach(TileInstanceManager::invalidate);
}
ContraptionRenderDispatcher.invalidateAll(); ContraptionRenderDispatcher.invalidateAll();
} }

View file

@ -7,8 +7,8 @@ import java.util.List;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; import com.jozufozu.flywheel.backend.instancing.IInstanceRendered;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.KineticNetwork; import com.simibubi.create.content.contraptions.KineticNetwork;
import com.simibubi.create.content.contraptions.RotationPropagator; import com.simibubi.create.content.contraptions.RotationPropagator;
@ -258,7 +258,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
effects.triggerOverStressedEffect(); effects.triggerOverStressedEffect();
if (clientPacket) if (clientPacket)
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> Backend.enqueueUpdate(this)); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this));
} }
public float getGeneratedSpeed() { public float getGeneratedSpeed() {
@ -557,7 +557,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
public void requestModelDataUpdate() { public void requestModelDataUpdate() {
super.requestModelDataUpdate(); super.requestModelDataUpdate();
if (!this.removed) { if (!this.removed) {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> Backend.enqueueUpdate(this)); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this));
} }
} }

View file

@ -2,8 +2,8 @@ package com.simibubi.create.content.contraptions.components.structureMovement.ch
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; import com.jozufozu.flywheel.backend.instancing.IInstanceRendered;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; 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)); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> playSound(false));
piston.chase(target, .4f, Chaser.LINEAR); piston.chase(target, .4f, Chaser.LINEAR);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> Backend.enqueueUpdate(this)); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this));
} }
public boolean isAttachedToBlock() { public boolean isAttachedToBlock() {

View file

@ -40,9 +40,9 @@ public class ContraptionInstanceManager extends TileInstanceManager {
} }
@Override @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; return true;
} }
@Nullable @Nullable
public ActorInstance createActor(Pair<Template.BlockInfo, MovementContext> actor) { public ActorInstance createActor(Pair<Template.BlockInfo, MovementContext> actor) {

View file

@ -18,6 +18,9 @@ import org.apache.commons.lang3.tuple.Pair;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.loading.ModelTemplate; import com.jozufozu.flywheel.backend.loading.ModelTemplate;
import com.jozufozu.flywheel.core.WorldContext; 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.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.CreateClient; 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.BlockModelRenderer;
import net.minecraft.client.renderer.BlockModelShapes; import net.minecraft.client.renderer.BlockModelShapes;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.RenderType; 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.WorldRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.world.LightType; import net.minecraft.world.LightType;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template; import net.minecraft.world.gen.feature.template.Template;
import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.data.EmptyModelData; import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.common.util.Lazy; import net.minecraftforge.common.util.Lazy;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber
public class ContraptionRenderDispatcher { public class ContraptionRenderDispatcher {
private static final Lazy<BlockModelRenderer> MODEL_RENDERER = Lazy.of(() -> new BlockModelRenderer(Minecraft.getInstance().getBlockColors())); private static final Lazy<BlockModelRenderer> MODEL_RENDERER = Lazy.of(() -> new BlockModelRenderer(Minecraft.getInstance().getBlockColors()));
private static final Lazy<BlockModelShapes> BLOCK_MODELS = Lazy.of(() -> Minecraft.getInstance().getModelManager().getBlockModelShapes()); private static final Lazy<BlockModelShapes> 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 camX = info.getProjectedView().x;
double camY = info.getProjectedView().y; double camY = info.getProjectedView().y;
double camZ = info.getProjectedView().z; 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(); removeDeadContraptions();
if (RENDERERS.isEmpty()) return; if (RENDERERS.isEmpty()) return;
RenderType layer = event.getType();
layer.startDrawing(); layer.startDrawing();
glEnable(GL_TEXTURE_3D); glEnable(GL_TEXTURE_3D);
@ -114,8 +121,8 @@ public class ContraptionRenderDispatcher {
ContraptionProgram structureShader = STRUCTURE.getProgram(AllProgramSpecs.STRUCTURE); ContraptionProgram structureShader = STRUCTURE.getProgram(AllProgramSpecs.STRUCTURE);
structureShader.bind(); structureShader.bind();
structureShader.uploadViewProjection(viewProjection); structureShader.uploadViewProjection(event.viewProjection);
structureShader.uploadCameraPos(camX, camY, camZ); structureShader.uploadCameraPos(event.camX, event.camY, event.camZ);
for (RenderedContraption renderer : RENDERERS.values()) { for (RenderedContraption renderer : RENDERERS.values()) {
renderer.doRenderLayer(layer, structureShader); renderer.doRenderLayer(layer, structureShader);
@ -124,7 +131,7 @@ public class ContraptionRenderDispatcher {
if (Backend.canUseInstancing()) { if (Backend.canUseInstancing()) {
for (RenderedContraption renderer : RENDERERS.values()) { 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); glActiveTexture(GL_TEXTURE0);
} }
@SubscribeEvent
public static void onRendererReload(ReloadRenderersEvent event) {
invalidateAll();
}
public static void render(AbstractContraptionEntity entity, Contraption contraption, public static void render(AbstractContraptionEntity entity, Contraption contraption,
ContraptionMatrices matrices, IRenderTypeBuffer buffers) { ContraptionMatrices matrices, IRenderTypeBuffer buffers) {
World world = entity.world; World world = entity.world;
@ -157,7 +169,7 @@ public class ContraptionRenderDispatcher {
if (contraption == null) { if (contraption == null) {
PlacementSimulationWorld renderWorld = setupRenderWorld(world, c); PlacementSimulationWorld renderWorld = setupRenderWorld(world, c);
contraption = new RenderedContraption(world, renderWorld, c); contraption = new RenderedContraption(renderWorld, c);
RENDERERS.put(entityId, contraption); RENDERERS.put(entityId, contraption);
} }
@ -183,7 +195,7 @@ public class ContraptionRenderDispatcher {
renderWorld.setTileEntities(c.presentTileEntities.values()); renderWorld.setTileEntities(c.presentTileEntities.values());
for (Template.BlockInfo info : c.getBlocks() for (Template.BlockInfo info : c.getBlocks()
.values()) .values())
// Skip individual lighting updates to prevent lag with large contraptions // Skip individual lighting updates to prevent lag with large contraptions
renderWorld.setBlockState(info.pos, info.state, 128); renderWorld.setBlockState(info.pos, info.state, 128);
@ -220,7 +232,7 @@ public class ContraptionRenderDispatcher {
MatrixStack m = matrices.contraptionStack; MatrixStack m = matrices.contraptionStack;
m.push(); m.push();
MatrixStacker.of(m) MatrixStacker.of(m)
.translate(blockInfo.pos); .translate(blockInfo.pos);
MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state);
if (movementBehaviour != null) if (movementBehaviour != null)
@ -264,7 +276,7 @@ public class ContraptionRenderDispatcher {
ForgeHooksClient.setRenderLayer(layer); ForgeHooksClient.setRenderLayer(layer);
BlockModelRenderer.enableCache(); BlockModelRenderer.enableCache();
for (Template.BlockInfo info : c.getBlocks() for (Template.BlockInfo info : c.getBlocks()
.values()) { .values()) {
BlockState state = info.state; BlockState state = info.state;
if (state.getRenderType() != BlockRenderType.MODEL) if (state.getRenderType() != BlockRenderType.MODEL)

View file

@ -58,7 +58,7 @@ public class RenderedContraption extends ContraptionWorldHolder {
private Matrix4f model; private Matrix4f model;
private AxisAlignedBB lightBox; private AxisAlignedBB lightBox;
public RenderedContraption(World world, PlacementSimulationWorld renderWorld, Contraption contraption) { public RenderedContraption(PlacementSimulationWorld renderWorld, Contraption contraption) {
super(contraption, renderWorld); super(contraption, renderWorld);
this.lighter = contraption.makeLighter(); this.lighter = contraption.makeLighter();
this.materialManager = new ContraptionMaterialManager(ContraptionRenderDispatcher.TILES); this.materialManager = new ContraptionMaterialManager(ContraptionRenderDispatcher.TILES);
@ -119,6 +119,7 @@ public class RenderedContraption extends ContraptionWorldHolder {
lighter.lightVolume.delete(); lighter.lightVolume.delete();
materialManager.delete();
kinetics.invalidate(); kinetics.invalidate();
} }

View file

@ -12,7 +12,7 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; 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.GridAlignedBB;
import com.jozufozu.flywheel.light.ILightUpdateListener; import com.jozufozu.flywheel.light.ILightUpdateListener;
import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.light.LightUpdater;
@ -267,7 +267,7 @@ public class BeltTileEntity extends KineticTileEntity implements ILightUpdateLis
belt.color = Optional.ofNullable(colorIn); belt.color = Optional.ofNullable(colorIn);
belt.markDirty(); belt.markDirty();
belt.sendData(); belt.sendData();
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> Backend.enqueueUpdate(belt)); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(belt));
} }
} }

View file

@ -9,8 +9,8 @@ import java.util.Set;
import org.apache.commons.lang3.tuple.Pair; 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.IInstanceRendered;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock.Shape; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock.Shape;
import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock; import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock;
@ -103,7 +103,7 @@ public class BeltTunnelTileEntity extends SmartTileEntity implements IInstanceRe
sides.addAll(flaps.keySet()); sides.addAll(flaps.keySet());
super.fromTag(state, compound, clientPacket); super.fromTag(state, compound, clientPacket);
if (clientPacket) if (clientPacket)
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> Backend.enqueueUpdate(this)); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this));
} }
public void updateTunnelConnections() { public void updateTunnelConnections() {

View file

@ -3,8 +3,8 @@ package com.simibubi.create.content.logistics.block.funnel;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; import com.jozufozu.flywheel.backend.instancing.IInstanceRendered;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.content.contraptions.goggles.IHaveHoveringInformation; import com.simibubi.create.content.contraptions.goggles.IHaveHoveringInformation;
@ -327,7 +327,7 @@ public class FunnelTileEntity extends SmartTileEntity implements IHaveHoveringIn
extractionCooldown = compound.getInt("TransferCooldown"); extractionCooldown = compound.getInt("TransferCooldown");
if (clientPacket) if (clientPacket)
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> Backend.enqueueUpdate(this)); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this));
} }
@Override @Override

View file

@ -3,9 +3,7 @@ package com.simibubi.create.events;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.RenderWork;
import com.jozufozu.flywheel.backend.instancing.TileInstanceManager;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllFluids; import com.simibubi.create.AllFluids;
@ -110,7 +108,7 @@ public class ClientEvents {
SoundScapes.tick(); SoundScapes.tick();
AnimationTickHolder.tick(); AnimationTickHolder.tick();
Backend.tick(); InstancedRenderDispatcher.tick();
ScrollValueHandler.tick(); ScrollValueHandler.tick();
CreateClient.SCHEMATIC_SENDER.tick(); CreateClient.SCHEMATIC_SENDER.tick();
@ -154,11 +152,8 @@ public class ClientEvents {
public static void onLoadWorld(WorldEvent.Load event) { public static void onLoadWorld(WorldEvent.Load event) {
IWorld world = event.getWorld(); IWorld world = event.getWorld();
if (world.isRemote() && world instanceof ClientWorld && !(world instanceof WrappedClientWorld)) { if (world.isRemote() && world instanceof ClientWorld && !(world instanceof WrappedClientWorld)) {
CreateClient.invalidateRenderers(world); CreateClient.invalidateRenderers();
AnimationTickHolder.reset(); 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) { public static void onUnloadWorld(WorldEvent.Unload event) {
if (event.getWorld() if (event.getWorld()
.isRemote()) { .isRemote()) {
CreateClient.invalidateRenderers(event.getWorld()); CreateClient.invalidateRenderers();
AnimationTickHolder.reset(); AnimationTickHolder.reset();
} }
} }
@ -199,8 +194,6 @@ public class ClientEvents {
RenderSystem.enableCull(); RenderSystem.enableCull();
ms.pop(); ms.pop();
RenderWork.runAll();
} }
@SubscribeEvent @SubscribeEvent

View file

@ -2,6 +2,7 @@ package com.simibubi.create.foundation.fluid;
import java.util.function.Function; import java.util.function.Function;
import com.jozufozu.flywheel.event.RenderLayerEvent;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.matrix.MatrixStack.Entry; import com.mojang.blaze3d.matrix.MatrixStack.Entry;
import com.mojang.blaze3d.vertex.IVertexBuilder; 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.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.fluid.Fluid; import net.minecraft.fluid.Fluid;
import net.minecraft.inventory.container.PlayerContainer; import net.minecraft.inventory.container.PlayerContainer;
import net.minecraft.util.Direction; 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.Direction.AxisDirection;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.MathHelper; 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.Vector3d;
import net.minecraft.util.math.vector.Vector3i; import net.minecraft.util.math.vector.Vector3i;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fluids.FluidAttributes; import net.minecraftforge.fluids.FluidAttributes;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber
public class FluidRenderer { public class FluidRenderer {
// If we draw to BufferBuilder that minecraft provides for RenderType.getTranslucent(), minecraft draws the contents // If we draw to BufferBuilder that minecraft provides for RenderType.getTranslucent(), minecraft draws the contents
@ -49,9 +51,10 @@ public class FluidRenderer {
return _builder; return _builder;
} }
public static void renderLayer(ClientWorld world, RenderType type, Matrix4f viewProjection, double camX, double camY, double camZ) { @SubscribeEvent
if (type == RenderType.getTranslucent()) { public static void renderLayer(RenderLayerEvent event) {
type.draw(_builder, 0, 0, 0); if (event.type == RenderType.getTranslucent()) {
event.type.draw(_builder, 0, 0, 0);
} }
} }
@ -76,9 +79,9 @@ public class FluidRenderer {
ms.push(); ms.push();
msr.centre() msr.centre()
.rotateY(AngleHelper.horizontalAngle(direction)) .rotateY(AngleHelper.horizontalAngle(direction))
.rotateX(direction == Direction.UP ? 0 : direction == Direction.DOWN ? 180 : 90) .rotateX(direction == Direction.UP ? 0 : direction == Direction.DOWN ? 180 : 90)
.unCentre(); .unCentre();
ms.translate(.5, 0, .5); ms.translate(.5, 0, .5);
float h = (float) (radius); float h = (float) (radius);
@ -91,21 +94,21 @@ public class FluidRenderer {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
ms.push(); ms.push();
renderTiledHorizontalFace(h, Direction.SOUTH, hMin, yMin, hMax, yMax, builder, ms, light, color, renderTiledHorizontalFace(h, Direction.SOUTH, hMin, yMin, hMax, yMax, builder, ms, light, color,
flowTexture); flowTexture);
ms.pop(); ms.pop();
msr.rotateY(90); msr.rotateY(90);
} }
if (progress != 1) if (progress != 1)
renderTiledVerticalFace(yMax, Direction.UP, hMin, hMin, hMax, hMax, builder, ms, light, color, renderTiledVerticalFace(yMax, Direction.UP, hMin, hMin, hMax, hMax, builder, ms, light, color,
stillTexture); stillTexture);
ms.pop(); ms.pop();
} }
public static void renderTiledFluidBB(FluidStack fluidStack, float xMin, float yMin, float zMin, float xMax, 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(); Fluid fluid = fluidStack.getFluid();
FluidAttributes fluidAttributes = fluid.getAttributes(); FluidAttributes fluidAttributes = fluid.getAttributes();
TextureAtlasSprite fluidTexture = Minecraft.getInstance() TextureAtlasSprite fluidTexture = Minecraft.getInstance()
@ -124,18 +127,18 @@ public class FluidRenderer {
ms.push(); ms.push();
if (fluidStack.getFluid() if (fluidStack.getFluid()
.getAttributes() .getAttributes()
.isLighterThanAir()) .isLighterThanAir())
MatrixStacker.of(ms) MatrixStacker.of(ms)
.translate(center) .translate(center)
.rotateX(180) .rotateX(180)
.translateBack(center); .translateBack(center);
for (Direction side : Iterate.directions) { for (Direction side : Iterate.directions) {
if (side == Direction.DOWN && !renderBottom) if (side == Direction.DOWN && !renderBottom)
continue; continue;
if (side.getAxis() if (side.getAxis()
.isHorizontal()) { .isHorizontal()) {
ms.push(); ms.push();
if (side.getAxisDirection() == AxisDirection.NEGATIVE) 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, 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 x2 = 0;
float z2 = 0; float z2 = 0;
for (float x1 = xMin; x1 < xMax; x1 = x2) { 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, 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; boolean X = face.getAxis() == Axis.X;
float h2 = 0; 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, 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(); Vector3i n = face.getDirectionVec();
Entry peek = ms.peek(); Entry peek = ms.peek();
@ -231,11 +234,11 @@ public class FluidRenderer {
int b = color & ff; int b = color & ff;
builder.vertex(peek.getModel(), x, y, z) builder.vertex(peek.getModel(), x, y, z)
.color(r, g, b, a) .color(r, g, b, a)
.texture(u, v) .texture(u, v)
.light(light) .light(light)
.normal(n.getX(), n.getY(), n.getZ()) .normal(n.getX(), n.getY(), n.getZ())
.endVertex(); .endVertex();
} }
} }

View file

@ -9,6 +9,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.OptifineHandler; 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 com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.block.BlockState; 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.minecraft.util.math.vector.Vector3d;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.MinecraftForge;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
@Mixin(WorldRenderer.class) @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_, 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_, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f p_228426_9_,
CallbackInfo ci) { 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(); Matrix4f viewProjection = view.copy();
viewProjection.multiplyBackward(Backend.getProjectionMatrix()); 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); GL20.glUseProgram(0);
} }
@ -63,7 +68,7 @@ public class RenderHooksMixin {
OptifineHandler.refresh(); OptifineHandler.refresh();
Backend.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()); viewProjection.multiplyBackward(Backend.getProjectionMatrix());
Vector3d cameraPos = info.getProjectedView(); 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); GL20.glUseProgram(0);
} }
@ -94,7 +99,7 @@ public class RenderHooksMixin {
@Inject(at = @At("TAIL"), method = "scheduleBlockRerenderIfNeeded") @Inject(at = @At("TAIL"), method = "scheduleBlockRerenderIfNeeded")
private void checkUpdate(BlockPos pos, BlockState lastState, BlockState newState, CallbackInfo ci) { private void checkUpdate(BlockPos pos, BlockState lastState, BlockState newState, CallbackInfo ci) {
Backend.tileInstanceManager.get(world) InstancedRenderDispatcher.get(world)
.update(world.getTileEntity(pos)); .update(world.getTileEntity(pos));
} }
} }

View file

@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 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.client.world.ClientWorld;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@ -24,7 +24,7 @@ public class TileRemoveMixin {
@Inject(at = @At("TAIL"), method = "remove") @Inject(at = @At("TAIL"), method = "remove")
private void onRemove(CallbackInfo ci) { private void onRemove(CallbackInfo ci) {
if (world instanceof ClientWorld) if (world instanceof ClientWorld)
Backend.tileInstanceManager.get(this.world) InstancedRenderDispatcher.get(this.world)
.remove((TileEntity) (Object) this); .remove((TileEntity) (Object) this);
} }
} }

View file

@ -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.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 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 com.jozufozu.flywheel.backend.instancing.TileInstanceManager;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@ -35,7 +35,7 @@ public class TileWorldHookMixin {
@Inject(at = @At("TAIL"), method = "addTileEntity") @Inject(at = @At("TAIL"), method = "addTileEntity")
private void onAddTile(TileEntity te, CallbackInfoReturnable<Boolean> cir) { private void onAddTile(TileEntity te, CallbackInfoReturnable<Boolean> cir) {
if (isRemote) { if (isRemote) {
Backend.tileInstanceManager.get(self) InstancedRenderDispatcher.get(self)
.queueAdd(te); .queueAdd(te);
} }
} }
@ -46,7 +46,7 @@ public class TileWorldHookMixin {
@Inject(at = @At(value = "INVOKE", target = "Ljava/util/Set;clear()V", ordinal = 0), method = "tickBlockEntities") @Inject(at = @At(value = "INVOKE", target = "Ljava/util/Set;clear()V", ordinal = 0), method = "tickBlockEntities")
private void onChunkUnload(CallbackInfo ci) { private void onChunkUnload(CallbackInfo ci) {
if (isRemote) { if (isRemote) {
TileInstanceManager kineticRenderer = Backend.tileInstanceManager.get(self); TileInstanceManager kineticRenderer = InstancedRenderDispatcher.get(self);
for (TileEntity tile : tileEntitiesToBeRemoved) { for (TileEntity tile : tileEntitiesToBeRemoved) {
kineticRenderer.remove(tile); kineticRenderer.remove(tile);
} }

View file

@ -7,7 +7,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 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 com.jozufozu.flywheel.light.LightUpdater;
import net.minecraft.client.multiplayer.ClientChunkProvider; import net.minecraft.client.multiplayer.ClientChunkProvider;
@ -46,7 +46,7 @@ public abstract class LightUpdateMixin extends AbstractChunkProvider {
.getY()) == sectionY) .getY()) == sectionY)
.map(Map.Entry::getValue) .map(Map.Entry::getValue)
.forEach(tile -> { .forEach(tile -> {
Backend.tileInstanceManager.get(world) InstancedRenderDispatcher.get(world)
.onLightUpdate(tile); .onLightUpdate(tile);
}); });
} }

View file

@ -5,8 +5,8 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 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.RenderWork;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.light.LightUpdater;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -36,7 +36,7 @@ public class NetworkLightUpdateMixin {
chunk.getTileEntityMap() chunk.getTileEntityMap()
.values() .values()
.forEach(tile -> { .forEach(tile -> {
Backend.tileInstanceManager.get(world) InstancedRenderDispatcher.get(world)
.onLightUpdate(tile); .onLightUpdate(tile);
}); });
} }

View file

@ -2,7 +2,6 @@ package com.simibubi.create.foundation.render;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; 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; import com.simibubi.create.foundation.render.effects.EffectsContext;
public class CreateFlywheelHandler { public class CreateFlywheelHandler {
@ -10,9 +9,5 @@ public class CreateFlywheelHandler {
Backend.register(ContraptionRenderDispatcher.TILES); Backend.register(ContraptionRenderDispatcher.TILES);
Backend.register(ContraptionRenderDispatcher.STRUCTURE); Backend.register(ContraptionRenderDispatcher.STRUCTURE);
Backend.register(EffectsContext.INSTANCE); Backend.register(EffectsContext.INSTANCE);
Backend.listeners.renderLayerListener(ContraptionRenderDispatcher::renderLayer);
Backend.listeners.renderLayerListener(FluidRenderer::renderLayer);
Backend.listeners.setupFrameListener(ContraptionRenderDispatcher::beginFrame);
Backend.listeners.refreshListener($ -> ContraptionRenderDispatcher.invalidateAll());
} }
} }

View file

@ -4,7 +4,8 @@ import java.util.Collections;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.ShaderContext; 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.backend.loading.ShaderTransformer;
import com.jozufozu.flywheel.core.shader.IMultiProgram; import com.jozufozu.flywheel.core.shader.IMultiProgram;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
@ -19,14 +20,14 @@ public class EffectsContext extends ShaderContext<SphereFilterProgram> {
} }
@Override @Override
protected IMultiProgram<SphereFilterProgram> loadSpecInternal(ShaderLoader loader, ProgramSpec spec) { protected IMultiProgram<SphereFilterProgram> loadSpecInternal(ShaderSources loader, ProgramSpec spec) {
return new SphereFilterProgram(loadProgram(loader, spec, Collections.emptyList())); return new SphereFilterProgram(loadProgram(loader, spec, Collections.emptyList()));
} }
@Override @Override
public void load(ShaderLoader loader) { public void load(ShaderSources loader) {
transformer = new ShaderTransformer() transformer = new ShaderTransformer()
.pushStage(loader::processIncludes); .pushStage(Shader::processIncludes);
loadProgramFromSpec(loader, Backend.getSpec(AllProgramSpecs.CHROMATIC)); loadProgramFromSpec(loader, Backend.getSpec(AllProgramSpecs.CHROMATIC));
} }
} }