forked from IrisShaders/Iris
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Render most opaque particles before translucent content
Relates to IrisShaders#137
- Loading branch information
1 parent
4d51ad7
commit fcc3977
Showing
6 changed files
with
171 additions
and
1 deletion.
There are no files selected for viewing
7 changes: 7 additions & 0 deletions
7
src/main/java/net/coderbot/iris/fantastic/ParticleRenderingPhase.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package net.coderbot.iris.fantastic; | ||
|
||
public enum ParticleRenderingPhase { | ||
EVERYTHING, | ||
OPAQUE, | ||
TRANSLUCENT | ||
} |
5 changes: 5 additions & 0 deletions
5
src/main/java/net/coderbot/iris/fantastic/PhasedParticleManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package net.coderbot.iris.fantastic; | ||
|
||
public interface PhasedParticleManager { | ||
void setParticleRenderingPhase(ParticleRenderingPhase phase); | ||
} |
88 changes: 88 additions & 0 deletions
88
src/main/java/net/coderbot/iris/mixin/fantastic/MixinParticleManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package net.coderbot.iris.mixin.fantastic; | ||
|
||
import com.google.common.collect.ImmutableList; | ||
import net.coderbot.iris.fantastic.ParticleRenderingPhase; | ||
import net.coderbot.iris.fantastic.PhasedParticleManager; | ||
import net.minecraft.client.particle.ParticleManager; | ||
import net.minecraft.client.particle.ParticleTextureSheet; | ||
import org.spongepowered.asm.mixin.Final; | ||
import org.spongepowered.asm.mixin.Mixin; | ||
import org.spongepowered.asm.mixin.Shadow; | ||
import org.spongepowered.asm.mixin.Unique; | ||
import org.spongepowered.asm.mixin.injection.At; | ||
import org.spongepowered.asm.mixin.injection.Redirect; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
/** | ||
* Extends the ParticleManager class to allow multiple phases of particle rendering. | ||
* | ||
* This is used to enable the rendering of known-opaque particles much earlier than other particles, most notably before | ||
* translucent content. Normally, particles behind translucent blocks are not visible on Fancy graphics, and a user must | ||
* enable the much more intensive Fabulous graphics option. This is not ideal because Fabulous graphics is fundamentally | ||
* incompatible with most shaderpacks. | ||
* | ||
* So what causes this? Essentially, on Fancy graphics, all particles are rendered after translucent terrain. Aside from | ||
* causing problems with particles being invisible, this also causes particles to write to the translucent depth buffer, | ||
* even when they are not translucent. This notably causes problems with particles on Sildur's Enhanced Default when | ||
* underwater. | ||
* | ||
* So, what these mixins do is try to render known-opaque particles right before entities are rendered and right after | ||
* opaque terrain has been rendered. This seems to be an acceptable injection point, and has worked in my testing. It | ||
* fixes issues with particles when underwater, fixes a vanilla bug, and doesn't have any significant performance hit. | ||
* A win-win! | ||
* | ||
* Unfortunately, there are limitations. Some particles rendering in texture sheets where translucency is supported. So, | ||
* even if an individual particle from that sheet is not translucent, it will still be treated as translucent, and thus | ||
* will not be affected by this patch. Without making more invasive and sweeping changes, there isn't a great way to get | ||
* around this. | ||
* | ||
* As the saying goes, "Work smarter, not harder." | ||
*/ | ||
@Mixin(ParticleManager.class) | ||
public class MixinParticleManager implements PhasedParticleManager { | ||
@Unique | ||
private ParticleRenderingPhase phase = ParticleRenderingPhase.EVERYTHING; | ||
|
||
@Shadow | ||
@Final | ||
private static List<ParticleTextureSheet> PARTICLE_TEXTURE_SHEETS; | ||
|
||
private static final List<ParticleTextureSheet> OPAQUE_PARTICLE_TEXTURE_SHEETS; | ||
|
||
static { | ||
OPAQUE_PARTICLE_TEXTURE_SHEETS = ImmutableList.of( | ||
ParticleTextureSheet.PARTICLE_SHEET_OPAQUE, | ||
ParticleTextureSheet.PARTICLE_SHEET_LIT, | ||
ParticleTextureSheet.CUSTOM, | ||
ParticleTextureSheet.NO_RENDER | ||
); | ||
} | ||
|
||
@Redirect(method = "renderParticles", at = @At(value = "FIELD", target = "Lnet/minecraft/client/particle/ParticleManager;PARTICLE_TEXTURE_SHEETS:Ljava/util/List;")) | ||
private List<ParticleTextureSheet> iris$selectParticlesToRender() { | ||
if (phase == ParticleRenderingPhase.TRANSLUCENT) { | ||
// Create a copy of the list | ||
// | ||
// We re-copy the list every time in case someone has added new particle texture sheets behind our back. | ||
List<ParticleTextureSheet> toRender = new ArrayList<>(PARTICLE_TEXTURE_SHEETS); | ||
|
||
// Remove all known opaque particle texture sheets. | ||
toRender.removeAll(OPAQUE_PARTICLE_TEXTURE_SHEETS); | ||
|
||
return toRender; | ||
} else if (phase == ParticleRenderingPhase.OPAQUE) { | ||
// Render only opaque particle sheets | ||
return OPAQUE_PARTICLE_TEXTURE_SHEETS; | ||
} else { | ||
// Don't override particle rendering | ||
return PARTICLE_TEXTURE_SHEETS; | ||
} | ||
} | ||
|
||
@Override | ||
public void setParticleRenderingPhase(ParticleRenderingPhase phase) { | ||
this.phase = phase; | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
src/main/java/net/coderbot/iris/mixin/fantastic/MixinWorldRenderer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package net.coderbot.iris.mixin.fantastic; | ||
|
||
import net.coderbot.iris.fantastic.ParticleRenderingPhase; | ||
import net.coderbot.iris.fantastic.PhasedParticleManager; | ||
import net.coderbot.iris.layer.GbufferProgram; | ||
import net.coderbot.iris.layer.GbufferPrograms; | ||
import net.minecraft.client.MinecraftClient; | ||
import net.minecraft.client.render.*; | ||
import net.minecraft.client.util.math.MatrixStack; | ||
import net.minecraft.util.math.Matrix4f; | ||
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.callback.CallbackInfo; | ||
|
||
/** | ||
* Uses the PhasedParticleManager changes to render opaque particles much earlier than other particles. | ||
* | ||
* See the comments in {@link MixinParticleManager} for more details. | ||
*/ | ||
@Mixin(WorldRenderer.class) | ||
public class MixinWorldRenderer { | ||
@Shadow | ||
@Final | ||
private MinecraftClient client; | ||
|
||
@Shadow | ||
@Final | ||
private BufferBuilderStorage bufferBuilders; | ||
|
||
@Inject(method = "render", at = @At("HEAD")) | ||
private void iris$resetParticleManagerPhase(MatrixStack matrices, float tickDelta, long limitTime, | ||
boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, | ||
LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, | ||
CallbackInfo callback) { | ||
((PhasedParticleManager) client.particleManager).setParticleRenderingPhase(ParticleRenderingPhase.EVERYTHING); | ||
} | ||
|
||
@Inject(method = "render", at = @At(value = "CONSTANT", args = "stringValue=entities")) | ||
private void iris$renderOpaqueParticles(MatrixStack matrices, float tickDelta, long limitTime, | ||
boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, | ||
LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, | ||
CallbackInfo callback) { | ||
VertexConsumerProvider.Immediate immediate = bufferBuilders.getEntityVertexConsumers(); | ||
|
||
((PhasedParticleManager) client.particleManager).setParticleRenderingPhase(ParticleRenderingPhase.OPAQUE); | ||
|
||
GbufferPrograms.push(GbufferProgram.TEXTURED_LIT); | ||
client.particleManager.renderParticles(matrices, immediate, lightmapTextureManager, camera, tickDelta); | ||
GbufferPrograms.pop(GbufferProgram.TEXTURED_LIT); | ||
|
||
((PhasedParticleManager) client.particleManager).setParticleRenderingPhase(ParticleRenderingPhase.TRANSLUCENT); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"required": true, | ||
"minVersion": "0.8", | ||
"package": "net.coderbot.iris.mixin.fantastic", | ||
"compatibilityLevel": "JAVA_8", | ||
"client": [ | ||
"MixinParticleManager", | ||
"MixinWorldRenderer" | ||
], | ||
"injectors": { | ||
"defaultRequire": 1 | ||
} | ||
} |