Skip to content

Commit

Permalink
Add angle-based section visibility path occlusion (#2811)
Browse files Browse the repository at this point in the history
This eliminates 8-13% of the rendered sections at higher render distances on average in testing, and correspondingly reduces graph search time by a similar amount.
  • Loading branch information
douira authored Oct 21, 2024
1 parent a94d3b7 commit 37dc5f6
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,16 @@ private static void processQueue(Visitor visitor,

{
if (useOcclusionCulling) {
var sectionVisibilityData = section.getVisibilityData();

// occlude paths through the section if it's being viewed at an angle where
// the other side can't possibly be seen
sectionVisibilityData &= getAngleVisibilityMask(viewport, section);

// When using occlusion culling, we can only traverse into neighbors for which there is a path of
// visibility through this chunk. This is determined by taking all the incoming paths to this chunk and
// creating a union of the outgoing paths from those.
connections = VisibilityEncoding.getConnections(section.getVisibilityData(), section.getIncomingDirections());
connections = VisibilityEncoding.getConnections(sectionVisibilityData, section.getIncomingDirections());
} else {
// Not using any occlusion culling, so traversing in any direction is legal.
connections = GraphDirectionSet.ALL;
Expand All @@ -79,6 +85,30 @@ private static void processQueue(Visitor visitor,
}
}

private static final long UP_DOWN_OCCLUDED = (1L << VisibilityEncoding.bit(GraphDirection.DOWN, GraphDirection.UP)) | (1L << VisibilityEncoding.bit(GraphDirection.UP, GraphDirection.DOWN));
private static final long NORTH_SOUTH_OCCLUDED = (1L << VisibilityEncoding.bit(GraphDirection.NORTH, GraphDirection.SOUTH)) | (1L << VisibilityEncoding.bit(GraphDirection.SOUTH, GraphDirection.NORTH));
private static final long WEST_EAST_OCCLUDED = (1L << VisibilityEncoding.bit(GraphDirection.WEST, GraphDirection.EAST)) | (1L << VisibilityEncoding.bit(GraphDirection.EAST, GraphDirection.WEST));

private static long getAngleVisibilityMask(Viewport viewport, RenderSection section) {
var transform = viewport.getTransform();
var dx = Math.abs(transform.x - section.getCenterX());
var dy = Math.abs(transform.y - section.getCenterY());
var dz = Math.abs(transform.z - section.getCenterZ());

var angleOcclusionMask = 0L;
if (dx > dy || dz > dy) {
angleOcclusionMask |= UP_DOWN_OCCLUDED;
}
if (dx > dz || dy > dz) {
angleOcclusionMask |= NORTH_SOUTH_OCCLUDED;
}
if (dy > dx || dz > dx) {
angleOcclusionMask |= WEST_EAST_OCCLUDED;
}

return ~angleOcclusionMask;
}

private static boolean isSectionVisible(RenderSection section, Viewport viewport, float maxDistance) {
return isWithinRenderDistance(viewport.getTransform(), section, maxDistance) && isWithinFrustum(viewport, section);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static long encode(@NotNull VisibilitySet occlusionData) {
return visibilityData;
}

private static int bit(int from, int to) {
public static int bit(int from, int to) {
return (from * 8) + to;
}

Expand Down

0 comments on commit 37dc5f6

Please sign in to comment.