Skip to content

Commit

Permalink
Remove unnecessarily strict comparisons in hidden surface elimination
Browse files Browse the repository at this point in the history
This doesn't eliminate any meaningful amount of
geometry and causes other regressions with things
such as powdered snow.
  • Loading branch information
jellysquid3 committed Jan 27, 2024
1 parent 4bd1002 commit c937156
Showing 1 changed file with 38 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import it.unimi.dsi.fastutil.Hash;
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenCustomHashMap;
import me.jellysquid.mods.sodium.client.util.DirectionUtil;
import net.minecraft.block.BlockState;
import net.minecraft.util.function.BooleanBiFunction;
import net.minecraft.util.math.BlockPos;
Expand Down Expand Up @@ -30,46 +31,60 @@ public BlockOcclusionCache() {
/**
* @param selfState The state of the block in the world
* @param view The world view for this render context
* @param pos The position of the block
* @param selfPos The position of the block
* @param facing The facing direction of the side to check
* @return True if the block side facing {@param dir} is not occluded, otherwise false
*/
public boolean shouldDrawSide(BlockState selfState, BlockView view, BlockPos pos, Direction facing) {
BlockPos.Mutable adjPos = this.cachedPositionObject;
adjPos.set(pos.getX() + facing.getOffsetX(), pos.getY() + facing.getOffsetY(), pos.getZ() + facing.getOffsetZ());
public boolean shouldDrawSide(BlockState selfState, BlockView view, BlockPos selfPos, Direction facing) {
BlockPos.Mutable otherPos = this.cachedPositionObject;
otherPos.set(selfPos.getX() + facing.getOffsetX(), selfPos.getY() + facing.getOffsetY(), selfPos.getZ() + facing.getOffsetZ());

BlockState adjState = view.getBlockState(adjPos);
BlockState otherState = view.getBlockState(otherPos);

if (selfState.isSideInvisible(adjState, facing)) {
// Blocks can define special behavior to control whether faces are rendered.
// This is mostly used by transparent blocks (Leaves, Glass, etc.) to not render interior faces between blocks
// of the same type.
if (selfState.isSideInvisible(otherState, facing)) {
return false;
} else if (adjState.isOpaque()) {
VoxelShape selfShape = selfState.getCullingFace(view, pos, facing);
VoxelShape adjShape = adjState.getCullingFace(view, adjPos, facing.getOpposite());
}

if (selfShape == VoxelShapes.fullCube() && adjShape == VoxelShapes.fullCube()) {
return false;
}
// If the other block is transparent, then it is unable to hide any geometry.
if (!otherState.isOpaque()) {
return true;
}

if (selfShape.isEmpty()) {
if (adjShape.isEmpty()){
return true; //example: top face of potted plants if top slab is placed above
}
else if (!adjState.isSideSolid(view,pos,facing.getOpposite(), SideShapeType.FULL)){
return true; //example: face of potted plants rendered if top stair placed above
}
}
// The cull shape of the block being rendered
VoxelShape selfShape = selfState.getCullingFace(view, selfPos, facing);

return this.lookup(selfShape, adjShape);
} else {
// If the block being rendered has an empty cull shape, intersection tests will always fail
if (selfShape.isEmpty()) {
return true;
}

// The cull shape of the block neighboring the one being rendered
VoxelShape otherShape = otherState.getCullingFace(view, otherPos, DirectionUtil.getOpposite(facing));

// If the other block has an empty cull shape, then it cannot hide any geometry
if (otherShape.isEmpty()) {
return true;
}

// If both blocks use a full-cube cull shape, then they will always hide the faces between each other
if (selfShape == VoxelShapes.fullCube() && otherShape == VoxelShapes.fullCube()) {
return false;
}

// No other simplifications apply, so we need to perform a full shape comparison, which is very slow
return this.lookup(selfShape, otherShape);
}

private boolean lookup(VoxelShape self, VoxelShape other) {
ShapeComparison comparison = this.cachedComparisonObject;
comparison.self = self;
comparison.other = other;

// Entries at the cache are promoted to the top of the table when accessed
// The entries at the bottom of the table are removed when it gets too large
return switch (this.comparisonLookupTable.getAndMoveToFirst(comparison)) {
case ENTRY_FALSE -> false;
case ENTRY_TRUE -> true;
Expand All @@ -80,6 +95,7 @@ private boolean lookup(VoxelShape self, VoxelShape other) {
private boolean calculate(ShapeComparison comparison) {
boolean result = VoxelShapes.matchesAnywhere(comparison.self, comparison.other, BooleanBiFunction.ONLY_FIRST);

// Remove entries while the table is too large
while (this.comparisonLookupTable.size() >= CACHE_SIZE) {
this.comparisonLookupTable.removeLastInt();
}
Expand Down

0 comments on commit c937156

Please sign in to comment.