Skip to content

Commit ece7936

Browse files
committed
Fix fluid renderer occluding when it shouldn't
There are two bugs fixed by this commit: * scratchPos gets clobbered which causes isFaceSturdy to be invoked with the wrong position. Fixed by refactoring the method body. * It is not enough to check isFaceSturdy to determine that a fluid is occluded, the occlusion shape must be checked too
1 parent 09c6306 commit ece7936

File tree

1 file changed

+23
-4
lines changed
  • src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline

1 file changed

+23
-4
lines changed

src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/FluidRenderer.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import net.minecraft.tags.FluidTags;
3333
import net.minecraft.util.Mth;
3434
import net.minecraft.world.level.BlockAndTintGetter;
35+
import net.minecraft.world.level.block.Block;
3536
import net.minecraft.world.level.block.SupportType;
3637
import net.minecraft.world.level.block.state.BlockState;
3738
import net.minecraft.world.level.material.Fluid;
@@ -75,14 +76,32 @@ public FluidRenderer(ColorProviderRegistry colorProviderRegistry, LightPipelineP
7576
}
7677

7778
private boolean isFluidOccluded(BlockAndTintGetter world, int x, int y, int z, Direction dir, Fluid fluid) {
79+
// Check if the fluid adjacent to us in the given direction is the same
80+
if (world.getFluidState(this.scratchPos.set(x + dir.getStepX(), y + dir.getStepY(), z + dir.getStepZ())).getType().isSame(fluid)) {
81+
return true;
82+
}
83+
84+
// Stricter than vanilla: check whether the containing block can occlude, has a sturdy face on the given side,
85+
// and has a solid occlusion shape. If so, assume the fluid inside is not visible on that side.
86+
// This avoids rendering the top face of water inside an upper waterlogged slab, for instance.
7887
BlockPos pos = this.scratchPos.set(x, y, z);
7988
BlockState blockState = world.getBlockState(pos);
80-
BlockPos adjPos = this.scratchPos.set(x + dir.getStepX(), y + dir.getStepY(), z + dir.getStepZ());
8189

82-
if (blockState.canOcclude()) {
83-
return world.getFluidState(adjPos).getType().isSame(fluid) || blockState.isFaceSturdy(world, pos, dir, SupportType.FULL);
90+
if (!blockState.canOcclude() || !blockState.isFaceSturdy(world, pos, dir, SupportType.FULL)) {
91+
return false;
92+
}
93+
94+
VoxelShape sideShape = blockState.getFaceOcclusionShape(world, pos, dir);
95+
if (sideShape == Shapes.block()) {
96+
// The face fills the 1x1 area, so the fluid is occluded
97+
return true;
98+
} else if (sideShape == Shapes.empty()) {
99+
// The face does not exist, so the fluid is not occluded
100+
return false;
101+
} else {
102+
// Check if the face fills the 1x1 area
103+
return Block.isShapeFullBlock(sideShape);
84104
}
85-
return world.getFluidState(adjPos).getType().isSame(fluid);
86105
}
87106

88107
private boolean isSideExposed(BlockAndTintGetter world, int x, int y, int z, Direction dir, float height) {

0 commit comments

Comments
 (0)