Jump to content

[1.19.2] Disabled chunk rendering doesn't work while camera is moving


SoLegendary

Recommended Posts

I'm trying to conditionally hide specific chunks by disabling their rendering logic. I've found that LevelRenderer does this using renderChunksInFrustum but I don't think this is the only place they are rendered.

I've got this mixin that (for testing purposes) just hides every 2nd chunk on the X axis:

@Mixin(LevelRenderer.class)
public abstract class LevelRendererMixin {

    @Final
    @Shadow
    private ObjectArrayList<LevelRenderer.RenderChunkInfo> renderChunksInFrustum;

    @Inject(
        method = "renderLevel(Lcom/mojang/blaze3d/vertex/PoseStack;FJZLnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/GameRenderer;Lnet/minecraft/client/renderer/LightTexture;Lcom/mojang/math/Matrix4f;)V",
        at = @At("HEAD")
    )
    private void renderlevel(PoseStack pPoseStack, float pPartialTick, long pFinishNanoTime, boolean pRenderBlockOutline, Camera pCamera, GameRenderer pGameRenderer, LightTexture pLightTexture, Matrix4f pProjectionMatrix, CallbackInfo ci) {
        if (OrthoviewClientEvents.isEnabled())
            renderChunksInFrustum.removeIf(chunkInfo -> chunkInfo.chunk.bb.minX % 32 == 0)
    }
}

While this does hide the chunks I expected (see below), it seems it only works while the camera is stationary. While the camera is moving, all chunks will still show, causing a flickering effect as you move around.

n1NCxKT.png

Note that the Orthoview flag in my mod is just the isometric camera being enabled, but this problem happens in the regular camera too so that isn't an issue.

Where is the logic to render chunks while the camera is moving and how can I apply the same conditions I want to it from my mixin?

Link to comment
Share on other sites

57 minutes ago, SoLegendary said:

I've found that LevelRenderer does this using renderChunksInFrustum but I don't think this is the only place they are rendered.

That's an incorrect assumption. What you should look for is where the chunks are added which happens within `renderLevel`, so every time the game loads a new area because of the camera moving, the chunks that were removed will flicker as they are added in and compiled in the next frame of execution. If you want to properly handle things, you should look into LevelRenderer#applyFrustum where the chunks are added to the field.

Link to comment
Share on other sites

Ok so i've got it mostly reliable now, and managed to force a frustum update every tick so it doesn't rely on the camera to move to update.

    @Final @Shadow private ObjectArrayList<LevelRenderer.RenderChunkInfo> renderChunksInFrustum;
    @Final @Shadow private AtomicReference<LevelRenderer.RenderChunkStorage> renderChunkStorage = new AtomicReference<>();
    @Final @Shadow private Minecraft minecraft;

    @Inject(
        method = "applyFrustum(Lnet/minecraft/client/renderer/culling/Frustum;)V",
        at = @At("HEAD"),
        cancellable = true
    )
    private void applyFrustum(Frustum pFrustum, CallbackInfo ci) {
        ci.cancel();

        if (!Minecraft.getInstance().isSameThread()) {
            throw new IllegalStateException("applyFrustum called from wrong thread: " + Thread.currentThread().getName());
        } else {
            this.minecraft.getProfiler().push("apply_frustum");
            this.renderChunksInFrustum.clear();

            LinkedHashSet<LevelRenderer.RenderChunkInfo> renderChunkInfos = (this.renderChunkStorage.get()).renderChunks;

            for(LevelRenderer.RenderChunkInfo chunkInfo : renderChunkInfos) {
                if (pFrustum.isVisible(chunkInfo.chunk.getBoundingBox())) {

                    for (LivingEntity entity : UnitClientEvents.getAllUnits()) {

                        Vec3 centre = chunkInfo.chunk.bb.getCenter();
                        Vec2 centre2d = new Vec2((float) centre.x(), (float) centre.z());
                        Vec2 entity2d = new Vec2((float) entity.getX(), (float) entity.getZ());

                        if (entity2d.distanceToSqr(centre2d) < 900) {
                            this.renderChunksInFrustum.add(chunkInfo);
                            break;
                        }
                    }
                }
            }
            this.minecraft.getProfiler().pop();
        }
    }

 

However, i'm testing out only rendering chunks close to specific entities (for testing, centre of the chunk must be within 30 blocks of the entity), which kind of works but only when the viewing player is at specific positions:
L79lz78.png

However, if I move the player too far away from the entity, all of these chunks disappear, and renderChunkInfos contains only 7 items, instead of the usual 1000+, so it's not even an issue of my filtering logic. It's not the case that the entity i'm using to test distance with no longer exists as it is still loaded clientside (the leftmost mob in the below image). It also doesn't seem to be a frustum issue as it still happens even as I move the camera around. What is causing this and why is it tied to the player position?

EDIT: by "too far away" I mean only a few blocks away, basically just 1 chunk further than away than in the top image, not out of normal render distance of course

2jm4vRX.png

Edited by SoLegendary
more details
Link to comment
Share on other sites

I think I found the issue: when the player is in an unloaded chunk (ie. has never been loaded before in the world) renderChunkInfos is reduced to only your current chunk and adjacent chunks, but since my code only allowed rendering of the chunks near the mob I specified, it never gets a chance to load anything else. The solution may be to allow the player's immediate chunk to be loaded to avoid this issue, though I hope I can still not actually render it somehow.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.