Use Forge particle culling

Before mod was checking frustum twice
This commit is contained in:
Asek3 committed 2023-09-04 14:45:01 +03:00
1 parent 607dd9f423
commit d11998a857
1 file changed
+5 -67
@@ -1,79 +1,17 @@
package me.jellysquid.mods.sodium.mixin.features.particle.cull;
import me.jellysquid.mods.sodium.client.SodiumClientMod;
import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.client.particle.ParticleTextureSheet;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.Frustum;
import net.minecraft.client.render.LightmapTextureManager;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.Box;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.ArrayDeque;
import java.util.Map;
import java.util.Queue;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
@Mixin(ParticleManager.class)
public class MixinParticleManager {
@Shadow
@Final
private Map<ParticleTextureSheet, Queue<Particle>> particles;
private final Queue<Particle> cachedQueue = new ArrayDeque<>();
private boolean useCulling;
@Inject(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider$Immediate;Lnet/minecraft/client/render/LightmapTextureManager;Lnet/minecraft/client/render/Camera;FLnet/minecraft/client/render/Frustum;)V", at = @At("HEAD"))
private void preRenderParticles(MatrixStack matrixStack, VertexConsumerProvider.Immediate immediate, LightmapTextureManager lightmapTextureManager, Camera camera, float f, Frustum frustum, CallbackInfo ci) {
// Setup the frustum state before rendering particles
this.useCulling = SodiumClientMod.options().performance.useParticleCulling;
}
@Redirect(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider$Immediate;Lnet/minecraft/client/render/LightmapTextureManager;Lnet/minecraft/client/render/Camera;FLnet/minecraft/client/render/Frustum;)V", at = @At(value = "INVOKE", target = "Ljava/util/Map;get(Ljava/lang/Object;)Ljava/lang/Object;"), remap = false)
private <V> V filterParticleList(Map<ParticleTextureSheet, Queue<Particle>> map, Object key, MatrixStack matrixStack, VertexConsumerProvider.Immediate immediate, LightmapTextureManager lightmapTextureManager, Camera camera, float f, Frustum frustum) {
Queue<Particle> queue = this.particles.get(key);
if (queue == null || queue.isEmpty()) {
return null;
}
SodiumWorldRenderer renderer = SodiumWorldRenderer.instanceNullable();
// If culling isn't enabled or available, simply return the queue as-is
if (renderer == null || !this.useCulling) {
return (V) queue;
}
// Filter particles which are not visible
Queue<Particle> filtered = this.cachedQueue;
filtered.clear();
for (Particle particle : queue) {
Box box = particle.getBoundingBox();
// Hack: Grow the particle's bounding box in order to work around mis-behaved particles
if (!renderer.isBoxVisible(box.minX - 1.0D, box.minY - 1.0D, box.minZ - 1.0D, box.maxX + 1.0D, box.maxY + 1.0D, box.maxZ + 1.0D)) {
continue;
}
filtered.add(particle);
}
return (V) filtered;
}
@Inject(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider$Immediate;Lnet/minecraft/client/render/LightmapTextureManager;Lnet/minecraft/client/render/Camera;FLnet/minecraft/client/render/Frustum;)V", at = @At("RETURN"))
private void postRenderParticles(MatrixStack matrixStack, VertexConsumerProvider.Immediate immediate, LightmapTextureManager lightmapTextureManager, Camera camera, float f, Frustum frustum, CallbackInfo ci) {
// Ensure particles don't linger in the temporary collection
this.cachedQueue.clear();
@ModifyVariable(method = "render", at = @At("HEAD"), ordinal = 0)
private Frustum checkOption(Frustum oldInstance) {
boolean useCulling = SodiumClientMod.options().performance.useParticleCulling;
return useCulling ? oldInstance : null;
}
}