Things here and there

- Move CreateClient.kineticRenderer to Backend
 - InstancedTileRenderers keep track of their own queuedUpdates
 - Sort of a listener system for some render events
This commit is contained in:
JozsefA 2021-05-04 23:56:50 -07:00
parent 55e3f50f64
commit 9736ba19b5
18 changed files with 208 additions and 119 deletions

View file

@ -3,7 +3,6 @@ package com.jozufozu.flywheel.backend;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -11,7 +10,6 @@ import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GLCapabilities; import org.lwjgl.opengl.GLCapabilities;
import com.jozufozu.flywheel.backend.core.BasicInstancedTileRenderer; import com.jozufozu.flywheel.backend.core.BasicInstancedTileRenderer;
import com.jozufozu.flywheel.backend.core.ContraptionContext;
import com.jozufozu.flywheel.backend.core.EffectsContext; import com.jozufozu.flywheel.backend.core.EffectsContext;
import com.jozufozu.flywheel.backend.core.WorldContext; import com.jozufozu.flywheel.backend.core.WorldContext;
import com.jozufozu.flywheel.backend.effects.EffectsHandler; import com.jozufozu.flywheel.backend.effects.EffectsHandler;
@ -21,7 +19,6 @@ import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
import com.jozufozu.flywheel.backend.instancing.IFlywheelWorld; import com.jozufozu.flywheel.backend.instancing.IFlywheelWorld;
import com.jozufozu.flywheel.backend.instancing.InstancedModel; import com.jozufozu.flywheel.backend.instancing.InstancedModel;
import com.jozufozu.flywheel.backend.instancing.MaterialSpec; import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.KineticDebugger; import com.simibubi.create.content.contraptions.KineticDebugger;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.utility.WorldAttached; import com.simibubi.create.foundation.utility.WorldAttached;
@ -42,25 +39,41 @@ 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 ShaderLoader shaderLoader = new ShaderLoader();
public static EffectsHandler effects; public static final FlywheelListeners listeners = new FlywheelListeners();
public static Matrix4f projectionMatrix = new Matrix4f();
public static GLCapabilities capabilities; public static GLCapabilities capabilities;
public static GlCompat compat; public static GlCompat compat;
public static WorldAttached<ConcurrentHashMap.KeySetView<TileEntity, Boolean>> queuedUpdates = new WorldAttached<>(ConcurrentHashMap::newKeySet);
public static EffectsHandler effects;
public static WorldAttached<BasicInstancedTileRenderer> tileRenderer = new WorldAttached<>(BasicInstancedTileRenderer::new);
private static Matrix4f projectionMatrix = new Matrix4f();
private static boolean instancingAvailable; private static boolean instancingAvailable;
private static boolean enabled; private static boolean enabled;
static Map<ResourceLocation, MaterialSpec<?>> materialRegistry = new HashMap<>(); static final Map<ResourceLocation, MaterialSpec<?>> materialRegistry = new HashMap<>();
static final Map<ResourceLocation, ShaderContext<?>> contexts = new HashMap<>(); static final Map<ResourceLocation, ShaderContext<?>> contexts = new HashMap<>();
static final Map<ResourceLocation, ProgramSpec> programSpecRegistry = new HashMap<>(); static final Map<ResourceLocation, ProgramSpec> programSpecRegistry = new HashMap<>();
static { static {
register(WorldContext.INSTANCE); register(WorldContext.INSTANCE);
register(ContraptionContext.INSTANCE);
register(EffectsContext.INSTANCE); register(EffectsContext.INSTANCE);
listeners.refreshListener(world -> {
if (canUseInstancing() && world != null) {
BasicInstancedTileRenderer tileRenderer = Backend.tileRenderer.get(world);
tileRenderer.invalidate();
world.loadedTileEntityList.forEach(tileRenderer::add);
}
});
listeners.setupFrameListener((world, stack, info, gameRenderer, lightTexture) -> {
Backend.tileRenderer.get(world)
.beginFrame(info);
});
listeners.renderLayerListener(Backend::renderLayer);
} }
public Backend() { public Backend() {
@ -161,35 +174,25 @@ public class Backend {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
ClientWorld world = mc.world; ClientWorld world = mc.world;
BasicInstancedTileRenderer kineticRenderer = CreateClient.kineticRenderer.get(world); BasicInstancedTileRenderer instancer = tileRenderer.get(world);
Entity renderViewEntity = mc.renderViewEntity; Entity renderViewEntity = mc.renderViewEntity;
kineticRenderer.tick(renderViewEntity.getX(), renderViewEntity.getY(), renderViewEntity.getZ()); instancer.tick(renderViewEntity.getX(), renderViewEntity.getY(), renderViewEntity.getZ());
ConcurrentHashMap.KeySetView<TileEntity, Boolean> map = queuedUpdates.get(world);
map
.forEach(te -> {
map.remove(te);
kineticRenderer.update(te);
});
} }
public static void renderLayer(RenderType layer, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) { public static void renderLayer(ClientWorld world, RenderType layer, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) {
if (!canUseInstancing()) return; if (!canUseInstancing(world)) return;
ClientWorld world = Minecraft.getInstance().world;
BasicInstancedTileRenderer kineticRenderer = CreateClient.kineticRenderer.get(world);
layer.startDrawing(); layer.startDrawing();
kineticRenderer.render(layer, viewProjection, cameraX, cameraY, cameraZ); tileRenderer.get(world)
.render(layer, viewProjection, cameraX, cameraY, cameraZ);
layer.endDrawing(); layer.endDrawing();
} }
public static void enqueueUpdate(TileEntity te) { public static void enqueueUpdate(TileEntity te) {
queuedUpdates.get(te.getWorld()).add(te); tileRenderer.get(te.getWorld()).queueUpdate(te);
} }
public static void reloadWorldRenderers() { public static void reloadWorldRenderers() {
@ -215,4 +218,12 @@ public class Backend {
public static Collection<ProgramSpec> allPrograms() { public static Collection<ProgramSpec> allPrograms() {
return programSpecRegistry.values(); return programSpecRegistry.values();
} }
public static Matrix4f getProjectionMatrix() {
return projectionMatrix;
}
public static void setProjectionMatrix(Matrix4f projectionMatrix) {
Backend.projectionMatrix = projectionMatrix;
}
} }

View file

@ -0,0 +1,65 @@
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

@ -27,10 +27,10 @@ public class BasicInstancedTileRenderer extends InstancedTileRenderer<BasicProgr
} }
@Override @Override
public void beginFrame(ActiveRenderInfo info, double cameraX, double cameraY, double cameraZ) { public void beginFrame(ActiveRenderInfo info) {
int cX = MathHelper.floor(cameraX); int cX = MathHelper.floor(info.getProjectedView().x);
int cY = MathHelper.floor(cameraY); int cY = MathHelper.floor(info.getProjectedView().y);
int cZ = MathHelper.floor(cameraZ); int cZ = MathHelper.floor(info.getProjectedView().z);
int dX = Math.abs(cX - originCoordinate.getX()); int dX = Math.abs(cX - originCoordinate.getX());
int dY = Math.abs(cY - originCoordinate.getY()); int dY = Math.abs(cY - originCoordinate.getY());
@ -45,7 +45,7 @@ public class BasicInstancedTileRenderer extends InstancedTileRenderer<BasicProgr
instancedTiles.forEach(this::add); instancedTiles.forEach(this::add);
} }
super.beginFrame(info, cameraX, cameraY, cameraZ); super.beginFrame(info);
} }
@Override @Override

View file

@ -3,6 +3,7 @@ package com.jozufozu.flywheel.backend.instancing;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -25,16 +26,17 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public abstract class InstancedTileRenderer<P extends BasicProgram> { public abstract class InstancedTileRenderer<P extends BasicProgram> {
protected ArrayList<TileEntity> queuedAdditions = new ArrayList<>(64);
protected Map<TileEntity, TileEntityInstance<?>> instances = new HashMap<>();
protected Map<TileEntity, ITickableInstance> tickableInstances = new HashMap<>();
protected Map<TileEntity, IDynamicInstance> dynamicInstances = new HashMap<>();
public final WorldContext<P> context; public final WorldContext<P> context;
protected Map<MaterialSpec<?>, RenderMaterial<P, ?>> materials = new HashMap<>(); protected final Map<MaterialSpec<?>, RenderMaterial<P, ?>> materials;
protected final ArrayList<TileEntity> queuedAdditions;
protected final ConcurrentHashMap.KeySetView<TileEntity, Boolean> queuedUpdates;
protected final Map<TileEntity, TileEntityInstance<?>> instances;
protected final Map<TileEntity, ITickableInstance> tickableInstances;
protected final Map<TileEntity, IDynamicInstance> dynamicInstances;
protected int frame; protected int frame;
protected int tick; protected int tick;
@ -42,9 +44,16 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
protected InstancedTileRenderer(WorldContext<P> context) { protected InstancedTileRenderer(WorldContext<P> context) {
this.context = context; this.context = context;
materials = new HashMap<>();
for (MaterialSpec<?> spec : Backend.allMaterials()) { for (MaterialSpec<?> spec : Backend.allMaterials()) {
materials.put(spec, spec.create(this)); materials.put(spec, spec.create(this));
} }
queuedUpdates = ConcurrentHashMap.newKeySet(64);
queuedAdditions = new ArrayList<>(64);
dynamicInstances = new HashMap<>();
tickableInstances = new HashMap<>();
instances = new HashMap<>();
} }
public abstract BlockPos getOriginCoordinate(); public abstract BlockPos getOriginCoordinate();
@ -74,9 +83,15 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
instance.tick(); instance.tick();
} }
} }
queuedUpdates.forEach(te -> {
queuedUpdates.remove(te);
update(te);
});
} }
public void beginFrame(ActiveRenderInfo info, double cameraX, double cameraY, double cameraZ) { public void beginFrame(ActiveRenderInfo info) {
frame++; frame++;
processQueuedAdditions(); processQueuedAdditions();
@ -86,9 +101,9 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
float lookZ = look.getZ(); float lookZ = look.getZ();
// integer camera pos // integer camera pos
int cX = (int) cameraX; int cX = (int) info.getProjectedView().x;
int cY = (int) cameraY; int cY = (int) info.getProjectedView().y;
int cZ = (int) cameraZ; int cZ = (int) info.getProjectedView().z;
if (dynamicInstances.size() > 0) { if (dynamicInstances.size() > 0) {
for (IDynamicInstance dyn : dynamicInstances.values()) { for (IDynamicInstance dyn : dynamicInstances.values()) {
@ -195,6 +210,12 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
queuedAdditions.add(tile); queuedAdditions.add(tile);
} }
public synchronized <T extends TileEntity> void queueUpdate(T tile) {
if (!Backend.canUseInstancing()) return;
queuedUpdates.add(tile);
}
protected synchronized void processQueuedAdditions() { protected synchronized void processQueuedAdditions() {
if (queuedAdditions.size() > 0) { if (queuedAdditions.size() > 0) {
queuedAdditions.forEach(this::addInternal); queuedAdditions.forEach(this::addInternal);

View file

@ -9,7 +9,6 @@ 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.OptifineHandler;
import com.jozufozu.flywheel.backend.core.BasicInstancedTileRenderer;
import com.jozufozu.flywheel.backend.core.PartialModel; import com.jozufozu.flywheel.backend.core.PartialModel;
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer; import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
@ -30,7 +29,6 @@ import com.simibubi.create.foundation.ponder.elements.WorldSectionElement;
import com.simibubi.create.foundation.render.AllMaterialSpecs; import com.simibubi.create.foundation.render.AllMaterialSpecs;
import com.simibubi.create.foundation.render.AllProgramSpecs; import com.simibubi.create.foundation.render.AllProgramSpecs;
import com.simibubi.create.foundation.render.SuperByteBufferCache; import com.simibubi.create.foundation.render.SuperByteBufferCache;
import com.simibubi.create.foundation.utility.WorldAttached;
import com.simibubi.create.foundation.utility.ghost.GhostBlocks; import com.simibubi.create.foundation.utility.ghost.GhostBlocks;
import com.simibubi.create.foundation.utility.outliner.Outliner; import com.simibubi.create.foundation.utility.outliner.Outliner;
@ -66,7 +64,6 @@ public class CreateClient {
public static SchematicHandler schematicHandler; public static SchematicHandler schematicHandler;
public static SchematicAndQuillHandler schematicAndQuillHandler; public static SchematicAndQuillHandler schematicAndQuillHandler;
public static SuperByteBufferCache bufferCache; public static SuperByteBufferCache bufferCache;
public static WorldAttached<BasicInstancedTileRenderer> kineticRenderer;
public static final Outliner outliner = new Outliner(); public static final Outliner outliner = new Outliner();
public static GhostBlocks ghostBlocks; public static GhostBlocks ghostBlocks;
@ -84,13 +81,13 @@ public class CreateClient {
modEventBus.addListener(AllParticleTypes::registerFactories); modEventBus.addListener(AllParticleTypes::registerFactories);
Backend.init(); Backend.init();
ContraptionRenderDispatcher.init();
OptifineHandler.init(); OptifineHandler.init();
} }
public static void clientInit(FMLClientSetupEvent event) { public static void clientInit(FMLClientSetupEvent event) {
AllProgramSpecs.init(); AllProgramSpecs.init();
AllMaterialSpecs.init(); AllMaterialSpecs.init();
kineticRenderer = new WorldAttached<>(BasicInstancedTileRenderer::new);
schematicSender = new ClientSchematicLoader(); schematicSender = new ClientSchematicLoader();
schematicHandler = new SchematicHandler(); schematicHandler = new SchematicHandler();
@ -221,10 +218,10 @@ public class CreateClient {
bufferCache.invalidate(); bufferCache.invalidate();
if (world != null) { if (world != null) {
kineticRenderer.get(world) Backend.tileRenderer.get(world)
.invalidate(); .invalidate();
} else { } else {
kineticRenderer.forEach(InstancedTileRenderer::invalidate); Backend.tileRenderer.forEach(InstancedTileRenderer::invalidate);
} }
ContraptionRenderDispatcher.invalidateAll(); ContraptionRenderDispatcher.invalidateAll();

View file

@ -37,11 +37,11 @@ public class ContraptionKineticRenderer extends InstancedTileRenderer<Contraptio
} }
@Override @Override
public void beginFrame(ActiveRenderInfo info, double cameraX, double cameraY, double cameraZ) { public void beginFrame(ActiveRenderInfo info) {
super.beginFrame(info, cameraX, cameraY, cameraZ); super.beginFrame(info);
actors.forEach(ActorInstance::beginFrame); actors.forEach(ActorInstance::beginFrame);
} }
@Override @Override
protected boolean shouldTick(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) { protected boolean shouldTick(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) {

View file

@ -34,6 +34,7 @@ import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.BlockModelRenderer; import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.BlockRendererDispatcher; import net.minecraft.client.renderer.BlockRendererDispatcher;
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;
@ -42,6 +43,7 @@ import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.IBakedModel;
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.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.world.LightType; import net.minecraft.world.LightType;
@ -55,6 +57,13 @@ public class ContraptionRenderDispatcher {
public static final Compartment<Pair<Contraption, Integer>> CONTRAPTION = new Compartment<>(); public static final Compartment<Pair<Contraption, Integer>> CONTRAPTION = new Compartment<>();
protected static PlacementSimulationWorld renderWorld; protected static PlacementSimulationWorld renderWorld;
public static void init() {
Backend.register(ContraptionContext.INSTANCE);
Backend.listeners.renderLayerListener(ContraptionRenderDispatcher::renderLayer);
Backend.listeners.setupFrameListener(ContraptionRenderDispatcher::beginFrame);
Backend.listeners.refreshListener($ -> ContraptionRenderDispatcher.invalidateAll());
}
public static void tick() { public static void tick() {
if (Minecraft.getInstance().isGamePaused()) return; if (Minecraft.getInstance().isGamePaused()) return;
@ -65,22 +74,25 @@ public class ContraptionRenderDispatcher {
} }
} }
public static void beginFrame(ActiveRenderInfo info, double camX, double camY, double camZ) { public static void beginFrame(ClientWorld world, MatrixStack stack, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture) {
double camX = info.getProjectedView().x;
double camY = info.getProjectedView().y;
double camZ = info.getProjectedView().z;
for (RenderedContraption renderer : renderers.values()) { for (RenderedContraption renderer : renderers.values()) {
renderer.beginFrame(info, camX, camY, camZ); renderer.beginFrame(info, camX, camY, camZ);
} }
} }
public static void renderLayer(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) { public static void renderLayer(ClientWorld world, RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) {
removeDeadContraptions(); removeDeadContraptions();
if (renderers.isEmpty()) return; if (renderers.isEmpty()) return;
layer.startDrawing(); layer.startDrawing();
GL11.glEnable(GL13.GL_TEXTURE_3D); GL11.glEnable(GL13.GL_TEXTURE_3D);
GL13.glActiveTexture(GL40.GL_TEXTURE4); // the shaders expect light volumes to be in texture 4 GL13.glActiveTexture(GL40.GL_TEXTURE4); // the shaders expect light volumes to be in texture 4
if (Backend.canUseVBOs()) { if (Backend.canUseVBOs()) {
ContraptionProgram structureShader = ContraptionContext.INSTANCE.getProgram(AllProgramSpecs.STRUCTURE); ContraptionProgram structureShader = ContraptionContext.INSTANCE.getProgram(AllProgramSpecs.STRUCTURE);
structureShader.bind(viewProjection, camX, camY, camZ, Backend.getDebugMode()); structureShader.bind(viewProjection, camX, camY, camZ, Backend.getDebugMode());
for (RenderedContraption renderer : renderers.values()) { for (RenderedContraption renderer : renderers.values()) {

View file

@ -89,7 +89,7 @@ public class RenderedContraption {
} }
public void beginFrame(ActiveRenderInfo info, double camX, double camY, double camZ) { public void beginFrame(ActiveRenderInfo info, double camX, double camY, double camZ) {
kinetics.beginFrame(info, camX, camY, camZ); kinetics.beginFrame(info);
AbstractContraptionEntity entity = contraption.entity; AbstractContraptionEntity entity = contraption.entity;
float pt = AnimationTickHolder.getPartialTicks(); float pt = AnimationTickHolder.getPartialTicks();

View file

@ -144,7 +144,7 @@ public class ClientEvents {
if (world.isRemote() && world instanceof ClientWorld && !(world instanceof WrappedClientWorld)) { if (world.isRemote() && world instanceof ClientWorld && !(world instanceof WrappedClientWorld)) {
CreateClient.invalidateRenderers(world); CreateClient.invalidateRenderers(world);
AnimationTickHolder.reset(); AnimationTickHolder.reset();
BasicInstancedTileRenderer renderer = CreateClient.kineticRenderer.get(world); BasicInstancedTileRenderer renderer = Backend.tileRenderer.get(world);
renderer.invalidate(); renderer.invalidate();
((ClientWorld) world).loadedTileEntityList.forEach(renderer::add); ((ClientWorld) world).loadedTileEntityList.forEach(renderer::add);
} }

View file

@ -7,8 +7,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.light.LightUpdater; import com.jozufozu.flywheel.backend.light.LightUpdater;
import com.simibubi.create.CreateClient;
import net.minecraft.client.multiplayer.ClientChunkProvider; import net.minecraft.client.multiplayer.ClientChunkProvider;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
@ -46,8 +46,8 @@ public abstract class LightUpdateMixin extends AbstractChunkProvider {
.getY()) == sectionY) .getY()) == sectionY)
.map(Map.Entry::getValue) .map(Map.Entry::getValue)
.forEach(tile -> { .forEach(tile -> {
CreateClient.kineticRenderer.get(world) Backend.tileRenderer.get(world)
.onLightUpdate(tile); .onLightUpdate(tile);
}); });
} }

View file

@ -5,9 +5,9 @@ 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.light.LightUpdater; import com.jozufozu.flywheel.backend.light.LightUpdater;
import com.simibubi.create.CreateClient;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.network.play.ClientPlayNetHandler; import net.minecraft.client.network.play.ClientPlayNetHandler;
@ -36,8 +36,8 @@ public class NetworkLightUpdateMixin {
chunk.getTileEntityMap() chunk.getTileEntityMap()
.values() .values()
.forEach(tile -> { .forEach(tile -> {
CreateClient.kineticRenderer.get(world) Backend.tileRenderer.get(world)
.onLightUpdate(tile); .onLightUpdate(tile);
}); });
} }

View file

@ -9,11 +9,8 @@ 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.core.BasicInstancedTileRenderer;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.ActiveRenderInfo;
@ -24,7 +21,6 @@ import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
@ -35,6 +31,13 @@ public class RenderHooksMixin {
@Shadow @Shadow
private ClientWorld world; private ClientWorld world;
@Inject(at = @At(value = "INVOKE", target = "net.minecraft.client.renderer.WorldRenderer.updateChunks(J)V"), method = "render")
private void setupFrame(MatrixStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_,
ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f p_228426_9_,
CallbackInfo ci) {
Backend.listeners.setupFrame(world, stack, info, gameRenderer, lightTexture);
}
/** /**
* JUSTIFICATION: This method is called once per layer per frame. It allows us to perform * JUSTIFICATION: This method is called once per layer per frame. It allows us to perform
* layer-correct custom rendering. RenderWorldLast is not refined enough for rendering world objects. * layer-correct custom rendering. RenderWorldLast is not refined enough for rendering world objects.
@ -42,36 +45,29 @@ public class RenderHooksMixin {
*/ */
@Inject(at = @At("TAIL"), method = "renderLayer") @Inject(at = @At("TAIL"), method = "renderLayer")
private void renderLayer(RenderType type, MatrixStack stack, double camX, double camY, double camZ, private void renderLayer(RenderType type, MatrixStack stack, double camX, double camY, double camZ,
CallbackInfo ci) { CallbackInfo ci) {
if (!Backend.available()) if (!Backend.available())
return; return;
Matrix4f view = stack.peek() Matrix4f view = stack.peek()
.getModel(); .getModel();
Matrix4f viewProjection = view.copy(); Matrix4f viewProjection = view.copy();
viewProjection.multiplyBackward(Backend.projectionMatrix); viewProjection.multiplyBackward(Backend.getProjectionMatrix());
Backend.renderLayer(type, viewProjection, camX, camY, camZ);
ContraptionRenderDispatcher.renderLayer(type, viewProjection, camX, camY, camZ);
Backend.listeners.renderLayer(world, type, viewProjection, camX, camY, camZ);
GL20.glUseProgram(0); GL20.glUseProgram(0);
} }
@Inject(at = @At(value = "INVOKE", target = "net.minecraft.client.renderer.WorldRenderer.updateChunks(J)V"), method = "render") @Inject(at = @At("TAIL"), method = "loadRenderers")
private void setupFrame(MatrixStack p_228426_1_, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, private void refresh(CallbackInfo ci) {
ActiveRenderInfo info, GameRenderer p_228426_7_, LightTexture p_228426_8_, Matrix4f p_228426_9_, OptifineHandler.refresh();
CallbackInfo ci) { Backend.refresh();
Vector3d cameraPos = info.getProjectedView();
double camX = cameraPos.getX();
double camY = cameraPos.getY();
double camZ = cameraPos.getZ();
CreateClient.kineticRenderer.get(world) Backend.listeners.refresh(world);
.beginFrame(info, camX, camY, camZ);
ContraptionRenderDispatcher.beginFrame(info, camX, camY, camZ);
} }
// Effects system
@Inject(method = "render", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/client/shader/ShaderGroup;render(F)V")) @Inject(method = "render", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/client/shader/ShaderGroup;render(F)V"))
private void disableTransparencyShaderDepth(MatrixStack p_228426_1_, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, ActiveRenderInfo p_228426_6_, GameRenderer p_228426_7_, LightTexture p_228426_8_, Matrix4f p_228426_9_, CallbackInfo ci) { private void disableTransparencyShaderDepth(MatrixStack p_228426_1_, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, ActiveRenderInfo p_228426_6_, GameRenderer p_228426_7_, LightTexture p_228426_8_, Matrix4f p_228426_9_, CallbackInfo ci) {
GlStateManager.depthMask(false); GlStateManager.depthMask(false);
@ -82,22 +78,11 @@ public class RenderHooksMixin {
Backend.effects.render(stack.peek().getModel()); Backend.effects.render(stack.peek().getModel());
} }
// Instancing
@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) {
CreateClient.kineticRenderer.get(world) Backend.tileRenderer.get(world)
.update(world.getTileEntity(pos)); .update(world.getTileEntity(pos));
} }
@Inject(at = @At("TAIL"), method = "loadRenderers")
private void refresh(CallbackInfo ci) {
ContraptionRenderDispatcher.invalidateAll();
OptifineHandler.refresh();
Backend.refresh();
if (Backend.canUseInstancing() && world != null) {
BasicInstancedTileRenderer kineticRenderer = CreateClient.kineticRenderer.get(world);
kineticRenderer.invalidate();
world.loadedTileEntityList.forEach(kineticRenderer::add);
}
}
} }

View file

@ -52,7 +52,7 @@ public abstract class StoreProjectionMatrixMixin {
@Inject(method = "loadProjectionMatrix", at = @At("TAIL")) @Inject(method = "loadProjectionMatrix", at = @At("TAIL"))
private void onProjectionMatrixLoad(Matrix4f projection, CallbackInfo ci) { private void onProjectionMatrixLoad(Matrix4f projection, CallbackInfo ci) {
if (shouldCopy) { if (shouldCopy) {
Backend.projectionMatrix = projection.copy(); Backend.setProjectionMatrix(projection.copy());
shouldCopy = false; shouldCopy = false;
} }
} }

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.simibubi.create.CreateClient; import com.jozufozu.flywheel.backend.Backend;
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)
CreateClient.kineticRenderer.get(this.world) Backend.tileRenderer.get(this.world)
.remove((TileEntity) (Object) this); .remove((TileEntity) (Object) this);
} }
} }

View file

@ -10,8 +10,8 @@ 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.core.BasicInstancedTileRenderer; import com.jozufozu.flywheel.backend.core.BasicInstancedTileRenderer;
import com.simibubi.create.CreateClient;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -35,8 +35,8 @@ 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) {
CreateClient.kineticRenderer.get(self) Backend.tileRenderer.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) {
BasicInstancedTileRenderer kineticRenderer = CreateClient.kineticRenderer.get(self); BasicInstancedTileRenderer kineticRenderer = Backend.tileRenderer.get(self);
for (TileEntity tile : tileEntitiesToBeRemoved) { for (TileEntity tile : tileEntitiesToBeRemoved) {
kineticRenderer.remove(tile); kineticRenderer.remove(tile);
} }

View file

@ -3,7 +3,7 @@
varying vec3 BoxCoord; varying vec3 BoxCoord;
uniform sampler3D uLightVolume; uniform sampler3D uLightVolume;
void FLWFinalizeColor(vec4 color) { void FLWFinalizeColor(inout vec4 color) {
#if defined(USE_FOG) #if defined(USE_FOG)
float a = color.a; float a = color.a;
float fog = clamp(FLWFogFactor(), 0., 1.); float fog = clamp(FLWFogFactor(), 0., 1.);

View file

@ -1,6 +1,6 @@
#flwinclude <"create:std/fog.glsl"> #flwinclude <"create:std/fog.glsl">
void FLWFinalizeColor(vec4 color) { void FLWFinalizeColor(inout vec4 color) {
#if defined(USE_FOG) #if defined(USE_FOG)
float a = color.a; float a = color.a;
float fog = clamp(FLWFogFactor(), 0., 1.); float fog = clamp(FLWFogFactor(), 0., 1.);

View file

@ -9,15 +9,13 @@ uniform vec2 uFogRange;
float FLWFogFactor() { float FLWFogFactor() {
return (uFogRange.y - FragDistance) / (uFogRange.y - uFogRange.x); return (uFogRange.y - FragDistance) / (uFogRange.y - uFogRange.x);
} }
#elif defined(USE_FOG_EXP2) #endif
#if defined(USE_FOG_EXP2)
uniform float uFogDensity; uniform float uFogDensity;
float FLWFogFactor() { float FLWFogFactor() {
float dist = FragDistance * uFogDensity; float dist = FragDistance * uFogDensity;
return 1. / exp2(dist * dist); return 1. / exp2(dist * dist);
}
#else
float FLWFogFactor() {
return 0.;
} }
#endif #endif