diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/LevelRendererMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/LevelRendererMixin.java index d48a6a501e..1959c82750 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/LevelRendererMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/LevelRendererMixin.java @@ -48,7 +48,11 @@ public abstract class LevelRendererMixin implements ILevelRenderer { @Unique private FeatureRenderDispatcher renderDispatcher; @Unique - private final OutlineRenderCommandQueue outlineRenderCommandQueue = new OutlineRenderCommandQueue(); + private RenderBuffers outlineRenderBuffers; + @Unique + private final OutlineRenderCommandQueue chamsRenderCommandQueue = new OutlineRenderCommandQueue(); + @Unique + private final OutlineRenderCommandQueue entityOutlineRenderCommandQueue = new OutlineRenderCommandQueue(); @Inject(method = "checkPoseStack", at = @At("HEAD"), cancellable = true) private void onCheckPoseStack(PoseStack poseStack, CallbackInfo ci) { @@ -79,8 +83,9 @@ private void onRenderLevelHead(GraphicsResourceAllocator resourceAllocator, bool @Inject(method = "submitEntities", at = @At("TAIL")) private void onSubmitEntities(PoseStack poseStack, LevelRenderState levelRenderState, SubmitNodeCollector output, CallbackInfo ci) { if (renderDispatcher == null) { + outlineRenderBuffers = new RenderBuffers(0); renderDispatcher = new FeatureRenderDispatcher( - renderBuffers, + outlineRenderBuffers, mc.getModelManager(), mc.getAtlasManager(), mc.font, @@ -88,14 +93,13 @@ private void onSubmitEntities(PoseStack poseStack, LevelRenderState levelRenderS ); } - draw(levelRenderState, poseStack, PostProcessShaders.CHAMS, _ -> Color.WHITE); - draw(levelRenderState, poseStack, PostProcessShaders.ENTITY_OUTLINE, entity -> Modules.get().get(ESP.class).getColor(entity)); + draw(levelRenderState, poseStack, PostProcessShaders.CHAMS, chamsRenderCommandQueue, _ -> Color.WHITE); + draw(levelRenderState, poseStack, PostProcessShaders.ENTITY_OUTLINE, entityOutlineRenderCommandQueue, entity -> Modules.get().get(ESP.class).getColor(entity)); } @Unique - private void draw(LevelRenderState worldState, PoseStack matrices, EntityShader shader, Function colorGetter) { + private void draw(LevelRenderState worldState, PoseStack matrices, EntityShader shader, OutlineRenderCommandQueue commandQueue, Function colorGetter) { var camera = worldState.cameraRenderState.pos; - var empty = true; for (var state : worldState.entityRenderStates) { Entity entity = ((IEntityRenderState) state).meteor$getEntity(); @@ -105,43 +109,57 @@ private void draw(LevelRenderState worldState, PoseStack matrices, EntityShader var color = colorGetter.apply(entity); if (color == null) continue; - outlineRenderCommandQueue.setColor(color); + commandQueue.setColor(color); var renderer = entityRenderDispatcher.getRenderer(state); var offset = renderer.getRenderOffset(state); matrices.pushPose(); matrices.translate(state.x - camera.x + offset.x, state.y - camera.y + offset.y, state.z - camera.z + offset.z); - renderer.submit(state, matrices, outlineRenderCommandQueue, worldState.cameraRenderState); + renderer.submit(state, matrices, commandQueue, worldState.cameraRenderState); matrices.popPose(); - - empty = false; } + } + + // executeOutline must run during the main pass, before vanilla uploads its staged buffers. + @Inject(method = "lambda$addMainPass$0", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;executeOutline(Lnet/minecraft/client/renderer/feature/FeatureRenderDispatcher$PreparedFrame;)V")) + private void addMainPass$submitEntityVertices(CallbackInfo ci) { + drawOutline(PostProcessShaders.CHAMS, chamsRenderCommandQueue); + drawOutline(PostProcessShaders.ENTITY_OUTLINE, entityOutlineRenderCommandQueue); + PostProcessShaders.submitEntityVertices(); + } - if (empty) - return; + @Unique + private void drawOutline(EntityShader shader, OutlineRenderCommandQueue commandQueue) { + if (commandQueue.submitsPerOrder.isEmpty()) return; meteor$pushEntityOutlineFramebuffer(shader.framebuffer); try { - try (var frame = renderDispatcher.prepareFrame(outlineRenderCommandQueue)) { + try (var frame = renderDispatcher.prepareFrame(commandQueue)) { executeOutline(frame); } } finally { - outlineRenderCommandQueue.submitsPerOrder.clear(); + commandQueue.submitsPerOrder.clear(); meteor$popEntityOutlineFramebuffer(); } } - @Inject(method = "lambda$addMainPass$0", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;executeOutline(Lnet/minecraft/client/renderer/feature/FeatureRenderDispatcher$PreparedFrame;)V", shift = At.Shift.AFTER)) - private void addMainPass$submitEntityVertices(CallbackInfo ci) { - PostProcessShaders.submitEntityVertices(); - } - @Inject(method = "resize", at = @At("HEAD")) private void onResize(int width, int height, CallbackInfo ci) { PostProcessShaders.onResized(width, height); } + @Inject(method = "endFrame", at = @At("TAIL")) + private void onEndFrame(CallbackInfo ci) { + if (outlineRenderBuffers != null) outlineRenderBuffers.endFrame(); + } + + @Inject(method = "close", at = @At("TAIL")) + private void onClose(CallbackInfo ci) { + if (outlineRenderBuffers != null) outlineRenderBuffers.close(); + if (renderDispatcher != null) renderDispatcher.close(); + } + // ILevelRenderer @Shadow @@ -156,10 +174,6 @@ private void onResize(int width, int height, CallbackInfo ci) { @Shadow @Final private EntityRenderDispatcher entityRenderDispatcher; - @Shadow - @Final - private RenderBuffers renderBuffers; - @Shadow protected abstract void executeOutline(FeatureRenderDispatcher.PreparedFrame featureFrame);