/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.google.common.collect.Lists * com.google.common.collect.Sets * it.unimi.dsi.fastutil.ints.Int2ObjectMap * it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap * it.unimi.dsi.fastutil.longs.Long2ObjectMap * it.unimi.dsi.fastutil.longs.Long2ObjectMap$Entry * it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap * it.unimi.dsi.fastutil.objects.ObjectArrayList * it.unimi.dsi.fastutil.objects.ObjectIterator * it.unimi.dsi.fastutil.objects.ObjectListIterator * org.joml.Matrix4f * org.joml.Matrix4fStack * org.joml.Matrix4fc * org.joml.Vector4f * org.jspecify.annotations.Nullable */ package net.minecraft.client.renderer; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.mojang.blaze3d.buffers.GpuBuffer; import com.mojang.blaze3d.buffers.GpuBufferSlice; import com.mojang.blaze3d.framegraph.FrameGraphBuilder; import com.mojang.blaze3d.framegraph.FramePass; import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.pipeline.TextureTarget; import com.mojang.blaze3d.platform.Lighting; import com.mojang.blaze3d.resource.GraphicsResourceAllocator; import com.mojang.blaze3d.resource.RenderTargetDescriptor; import com.mojang.blaze3d.resource.ResourceHandle; import com.mojang.blaze3d.systems.RenderPass; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.textures.AddressMode; import com.mojang.blaze3d.textures.FilterMode; import com.mojang.blaze3d.textures.GpuSampler; import com.mojang.blaze3d.textures.GpuTextureView; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexFormat; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectIterator; import it.unimi.dsi.fastutil.objects.ObjectListIterator; import java.util.ArrayList; import java.util.EnumMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.OptionalDouble; import java.util.Set; import java.util.SortedSet; import net.minecraft.SharedConstants; import net.minecraft.client.Camera; import net.minecraft.client.CloudStatus; import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; import net.minecraft.client.PrioritizeChunkUpdates; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.CloudRenderer; import net.minecraft.client.renderer.DynamicUniforms; import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.LevelTargetBundle; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.PostChain; import net.minecraft.client.renderer.RenderBuffers; import net.minecraft.client.renderer.SectionOcclusionGraph; import net.minecraft.client.renderer.ShapeRenderer; import net.minecraft.client.renderer.Sheets; import net.minecraft.client.renderer.SkyRenderer; import net.minecraft.client.renderer.SubmitNodeCollector; import net.minecraft.client.renderer.SubmitNodeStorage; import net.minecraft.client.renderer.ViewArea; import net.minecraft.client.renderer.WeatherEffectRenderer; import net.minecraft.client.renderer.WorldBorderRenderer; import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState; import net.minecraft.client.renderer.chunk.ChunkSectionLayer; import net.minecraft.client.renderer.chunk.ChunkSectionLayerGroup; import net.minecraft.client.renderer.chunk.ChunkSectionsToRender; import net.minecraft.client.renderer.chunk.CompiledSectionMesh; import net.minecraft.client.renderer.chunk.RenderRegionCache; import net.minecraft.client.renderer.chunk.SectionBuffers; import net.minecraft.client.renderer.chunk.SectionMesh; import net.minecraft.client.renderer.chunk.SectionRenderDispatcher; import net.minecraft.client.renderer.chunk.TranslucencyPointOfView; import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.client.renderer.debug.DebugRenderer; import net.minecraft.client.renderer.debug.GameTestBlockHighlightRenderer; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.state.EntityRenderState; import net.minecraft.client.renderer.feature.FeatureRenderDispatcher; import net.minecraft.client.renderer.feature.ModelFeatureRenderer; import net.minecraft.client.renderer.gizmos.DrawableGizmoPrimitives; import net.minecraft.client.renderer.rendertype.RenderTypes; import net.minecraft.client.renderer.state.BlockBreakingRenderState; import net.minecraft.client.renderer.state.BlockOutlineRenderState; import net.minecraft.client.renderer.state.CameraRenderState; import net.minecraft.client.renderer.state.LevelRenderState; import net.minecraft.client.renderer.state.ParticlesRenderState; import net.minecraft.client.renderer.state.SkyRenderState; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.resources.model.ModelBakery; import net.minecraft.client.server.IntegratedServer; import net.minecraft.core.BlockPos; import net.minecraft.core.SectionPos; import net.minecraft.gizmos.Gizmos; import net.minecraft.gizmos.SimpleGizmoCollector; import net.minecraft.resources.Identifier; import net.minecraft.server.level.BlockDestructionProgress; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.ResourceManagerReloadListener; import net.minecraft.util.ARGB; import net.minecraft.util.Brightness; import net.minecraft.util.Mth; import net.minecraft.util.Util; import net.minecraft.util.VisibleForDebug; import net.minecraft.util.profiling.Profiler; import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.TickRateManager; import net.minecraft.world.attribute.EnvironmentAttributes; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.material.FogType; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import org.joml.Matrix4f; import org.joml.Matrix4fStack; import org.joml.Matrix4fc; import org.joml.Vector4f; import org.jspecify.annotations.Nullable; public class LevelRenderer implements ResourceManagerReloadListener, AutoCloseable { private static final Identifier TRANSPARENCY_POST_CHAIN_ID = Identifier.withDefaultNamespace("transparency"); private static final Identifier ENTITY_OUTLINE_POST_CHAIN_ID = Identifier.withDefaultNamespace("entity_outline"); public static final int SECTION_SIZE = 16; public static final int HALF_SECTION_SIZE = 8; public static final int NEARBY_SECTION_DISTANCE_IN_BLOCKS = 32; private static final int MINIMUM_TRANSPARENT_SORT_COUNT = 15; private static final float CHUNK_VISIBILITY_THRESHOLD = 0.3f; private final Minecraft minecraft; private final EntityRenderDispatcher entityRenderDispatcher; private final BlockEntityRenderDispatcher blockEntityRenderDispatcher; private final RenderBuffers renderBuffers; private @Nullable SkyRenderer skyRenderer; private final CloudRenderer cloudRenderer = new CloudRenderer(); private final WorldBorderRenderer worldBorderRenderer = new WorldBorderRenderer(); private final WeatherEffectRenderer weatherEffectRenderer = new WeatherEffectRenderer(); private final ParticlesRenderState particlesRenderState = new ParticlesRenderState(); public final DebugRenderer debugRenderer = new DebugRenderer(); public final GameTestBlockHighlightRenderer gameTestBlockHighlightRenderer = new GameTestBlockHighlightRenderer(); private @Nullable ClientLevel level; private final SectionOcclusionGraph sectionOcclusionGraph = new SectionOcclusionGraph(); private final ObjectArrayList visibleSections = new ObjectArrayList(10000); private final ObjectArrayList nearbyVisibleSections = new ObjectArrayList(50); private @Nullable ViewArea viewArea; private int ticks; private final Int2ObjectMap destroyingBlocks = new Int2ObjectOpenHashMap(); private final Long2ObjectMap> destructionProgress = new Long2ObjectOpenHashMap(); private @Nullable RenderTarget entityOutlineTarget; private final LevelTargetBundle targets = new LevelTargetBundle(); private int lastCameraSectionX = Integer.MIN_VALUE; private int lastCameraSectionY = Integer.MIN_VALUE; private int lastCameraSectionZ = Integer.MIN_VALUE; private double prevCamX = Double.MIN_VALUE; private double prevCamY = Double.MIN_VALUE; private double prevCamZ = Double.MIN_VALUE; private double prevCamRotX = Double.MIN_VALUE; private double prevCamRotY = Double.MIN_VALUE; private @Nullable SectionRenderDispatcher sectionRenderDispatcher; private int lastViewDistance = -1; private boolean captureFrustum; private @Nullable Frustum capturedFrustum; private @Nullable BlockPos lastTranslucentSortBlockPos; private int translucencyResortIterationIndex; private final LevelRenderState levelRenderState; private final SubmitNodeStorage submitNodeStorage; private final FeatureRenderDispatcher featureRenderDispatcher; private @Nullable GpuSampler chunkLayerSampler; private final SimpleGizmoCollector collectedGizmos = new SimpleGizmoCollector(); public LevelRenderer(Minecraft minecraft, EntityRenderDispatcher entityRenderDispatcher, BlockEntityRenderDispatcher blockEntityRenderDispatcher, RenderBuffers renderBuffers, LevelRenderState levelRenderState, FeatureRenderDispatcher featureRenderDispatcher) { this.minecraft = minecraft; this.entityRenderDispatcher = entityRenderDispatcher; this.blockEntityRenderDispatcher = blockEntityRenderDispatcher; this.renderBuffers = renderBuffers; this.submitNodeStorage = featureRenderDispatcher.getSubmitNodeStorage(); this.levelRenderState = levelRenderState; this.featureRenderDispatcher = featureRenderDispatcher; } @Override public void close() { if (this.entityOutlineTarget != null) { this.entityOutlineTarget.destroyBuffers(); } if (this.skyRenderer != null) { this.skyRenderer.close(); } if (this.chunkLayerSampler != null) { this.chunkLayerSampler.close(); } this.cloudRenderer.close(); } @Override public void onResourceManagerReload(ResourceManager resourceManager) { this.initOutline(); if (this.skyRenderer != null) { this.skyRenderer.close(); } this.skyRenderer = new SkyRenderer(this.minecraft.getTextureManager(), this.minecraft.getAtlasManager()); } public void initOutline() { if (this.entityOutlineTarget != null) { this.entityOutlineTarget.destroyBuffers(); } this.entityOutlineTarget = new TextureTarget("Entity Outline", this.minecraft.getWindow().getWidth(), this.minecraft.getWindow().getHeight(), true); } private @Nullable PostChain getTransparencyChain() { if (!Minecraft.useShaderTransparency()) { return null; } PostChain chain = this.minecraft.getShaderManager().getPostChain(TRANSPARENCY_POST_CHAIN_ID, LevelTargetBundle.SORTING_TARGETS); if (chain == null) { this.minecraft.options.improvedTransparency().set(false); this.minecraft.options.save(); } return chain; } public void doEntityOutline() { if (this.shouldShowEntityOutlines()) { this.entityOutlineTarget.blitAndBlendToTexture(this.minecraft.getMainRenderTarget().getColorTextureView()); } } protected boolean shouldShowEntityOutlines() { return !this.minecraft.gameRenderer.isPanoramicMode() && this.entityOutlineTarget != null && this.minecraft.player != null; } public void setLevel(@Nullable ClientLevel level) { this.lastCameraSectionX = Integer.MIN_VALUE; this.lastCameraSectionY = Integer.MIN_VALUE; this.lastCameraSectionZ = Integer.MIN_VALUE; this.level = level; if (level != null) { this.allChanged(); } else { this.entityRenderDispatcher.resetCamera(); if (this.viewArea != null) { this.viewArea.releaseAllBuffers(); this.viewArea = null; } if (this.sectionRenderDispatcher != null) { this.sectionRenderDispatcher.dispose(); } this.sectionRenderDispatcher = null; this.sectionOcclusionGraph.waitAndReset(null); this.clearVisibleSections(); } this.gameTestBlockHighlightRenderer.clear(); } private void clearVisibleSections() { this.visibleSections.clear(); this.nearbyVisibleSections.clear(); } public void allChanged() { if (this.level == null) { return; } this.level.clearTintCaches(); if (this.sectionRenderDispatcher == null) { this.sectionRenderDispatcher = new SectionRenderDispatcher(this.level, this, Util.backgroundExecutor(), this.renderBuffers, this.minecraft.getBlockRenderer(), this.minecraft.getBlockEntityRenderDispatcher()); } else { this.sectionRenderDispatcher.setLevel(this.level); } this.cloudRenderer.markForRebuild(); ItemBlockRenderTypes.setCutoutLeaves(this.minecraft.options.cutoutLeaves().get()); this.lastViewDistance = this.minecraft.options.getEffectiveRenderDistance(); if (this.viewArea != null) { this.viewArea.releaseAllBuffers(); } this.sectionRenderDispatcher.clearCompileQueue(); this.viewArea = new ViewArea(this.sectionRenderDispatcher, this.level, this.minecraft.options.getEffectiveRenderDistance(), this); this.sectionOcclusionGraph.waitAndReset(this.viewArea); this.clearVisibleSections(); Camera camera = this.minecraft.gameRenderer.getMainCamera(); this.viewArea.repositionCamera(SectionPos.of(camera.position())); } public void resize(int width, int height) { this.needsUpdate(); if (this.entityOutlineTarget != null) { this.entityOutlineTarget.resize(width, height); } } public @Nullable String getSectionStatistics() { if (this.viewArea == null) { return null; } int totalSections = this.viewArea.sections.length; int rendered = this.countRenderedSections(); return String.format(Locale.ROOT, "C: %d/%d %sD: %d, %s", rendered, totalSections, this.minecraft.smartCull ? "(s) " : "", this.lastViewDistance, this.sectionRenderDispatcher == null ? "null" : this.sectionRenderDispatcher.getStats()); } public @Nullable SectionRenderDispatcher getSectionRenderDispatcher() { return this.sectionRenderDispatcher; } public double getTotalSections() { return this.viewArea == null ? 0.0 : (double)this.viewArea.sections.length; } public double getLastViewDistance() { return this.lastViewDistance; } public int countRenderedSections() { int rendered = 0; for (SectionRenderDispatcher.RenderSection section : this.visibleSections) { if (!section.getSectionMesh().hasRenderableLayers()) continue; ++rendered; } return rendered; } public void onChangeMaxAnisotropy() { if (this.chunkLayerSampler != null) { this.chunkLayerSampler.close(); } this.chunkLayerSampler = null; } public @Nullable String getEntityStatistics() { if (this.level == null) { return null; } return "E: " + this.levelRenderState.entityRenderStates.size() + "/" + this.level.getEntityCount() + ", SD: " + this.level.getServerSimulationDistance(); } private void cullTerrain(Camera camera, Frustum frustum, boolean spectator) { Vec3 cameraPos = camera.position(); if (this.minecraft.options.getEffectiveRenderDistance() != this.lastViewDistance) { this.allChanged(); } ProfilerFiller profiler = Profiler.get(); profiler.push("repositionCamera"); int cameraSectionX = SectionPos.posToSectionCoord(cameraPos.x()); int cameraSectionY = SectionPos.posToSectionCoord(cameraPos.y()); int cameraSectionZ = SectionPos.posToSectionCoord(cameraPos.z()); if (this.lastCameraSectionX != cameraSectionX || this.lastCameraSectionY != cameraSectionY || this.lastCameraSectionZ != cameraSectionZ) { this.lastCameraSectionX = cameraSectionX; this.lastCameraSectionY = cameraSectionY; this.lastCameraSectionZ = cameraSectionZ; this.viewArea.repositionCamera(SectionPos.of(cameraPos)); this.worldBorderRenderer.invalidate(); } this.sectionRenderDispatcher.setCameraPosition(cameraPos); double camX = Math.floor(cameraPos.x / 8.0); double camY = Math.floor(cameraPos.y / 8.0); double camZ = Math.floor(cameraPos.z / 8.0); if (camX != this.prevCamX || camY != this.prevCamY || camZ != this.prevCamZ) { this.sectionOcclusionGraph.invalidate(); } this.prevCamX = camX; this.prevCamY = camY; this.prevCamZ = camZ; profiler.pop(); if (this.capturedFrustum == null) { boolean smartCull = this.minecraft.smartCull; if (spectator && this.level.getBlockState(camera.blockPosition()).isSolidRender()) { smartCull = false; } profiler.push("updateSOG"); this.sectionOcclusionGraph.update(smartCull, camera, frustum, (List)this.visibleSections, this.level.getChunkSource().getLoadedEmptySections()); profiler.pop(); double camRotX = Math.floor(camera.xRot() / 2.0f); double camRotY = Math.floor(camera.yRot() / 2.0f); if (this.sectionOcclusionGraph.consumeFrustumUpdate() || camRotX != this.prevCamRotX || camRotY != this.prevCamRotY) { profiler.push("applyFrustum"); this.applyFrustum(LevelRenderer.offsetFrustum(frustum)); profiler.pop(); this.prevCamRotX = camRotX; this.prevCamRotY = camRotY; } } } public static Frustum offsetFrustum(Frustum frustum) { return new Frustum(frustum).offsetToFullyIncludeCameraCube(8); } private void applyFrustum(Frustum frustum) { if (!Minecraft.getInstance().isSameThread()) { throw new IllegalStateException("applyFrustum called from wrong thread: " + Thread.currentThread().getName()); } this.clearVisibleSections(); this.sectionOcclusionGraph.addSectionsInFrustum(frustum, (List)this.visibleSections, (List)this.nearbyVisibleSections); } public void addRecentlyCompiledSection(SectionRenderDispatcher.RenderSection section) { this.sectionOcclusionGraph.schedulePropagationFrom(section); } private Frustum prepareCullFrustum(Matrix4f modelViewMatrix, Matrix4f projectionMatrixForCulling, Vec3 cameraPos) { Frustum frustum; if (this.capturedFrustum != null && !this.captureFrustum) { frustum = this.capturedFrustum; } else { frustum = new Frustum(modelViewMatrix, projectionMatrixForCulling); frustum.prepare(cameraPos.x(), cameraPos.y(), cameraPos.z()); } if (this.captureFrustum) { this.capturedFrustum = frustum; this.captureFrustum = false; } return frustum; } public void renderLevel(GraphicsResourceAllocator resourceAllocator, DeltaTracker deltaTracker, boolean renderOutline, Camera camera, Matrix4f modelViewMatrix, Matrix4f projectionMatrix, Matrix4f projectionMatrixForCulling, GpuBufferSlice terrainFog, Vector4f fogColor, boolean shouldRenderSky) { int cloudColor; float deltaPartialTick = deltaTracker.getGameTimeDeltaPartialTick(false); this.levelRenderState.gameTime = this.level.getGameTime(); this.blockEntityRenderDispatcher.prepare(camera); this.entityRenderDispatcher.prepare(camera, this.minecraft.crosshairPickEntity); final ProfilerFiller profiler = Profiler.get(); profiler.push("populateLightUpdates"); this.level.pollLightUpdates(); profiler.popPush("runLightUpdates"); this.level.getChunkSource().getLightEngine().runLightUpdates(); profiler.popPush("prepareCullFrustum"); Vec3 cameraPos = camera.position(); Frustum frustum = this.prepareCullFrustum(modelViewMatrix, projectionMatrixForCulling, cameraPos); profiler.popPush("cullTerrain"); this.cullTerrain(camera, frustum, this.minecraft.player.isSpectator()); profiler.popPush("compileSections"); this.compileSections(camera); profiler.popPush("extract"); profiler.push("entities"); this.extractVisibleEntities(camera, frustum, deltaTracker, this.levelRenderState); profiler.popPush("blockEntities"); this.extractVisibleBlockEntities(camera, deltaPartialTick, this.levelRenderState); profiler.popPush("blockOutline"); this.extractBlockOutline(camera, this.levelRenderState); profiler.popPush("blockBreaking"); this.extractBlockDestroyAnimation(camera, this.levelRenderState); profiler.popPush("weather"); this.weatherEffectRenderer.extractRenderState(this.level, this.ticks, deltaPartialTick, cameraPos, this.levelRenderState.weatherRenderState); profiler.popPush("sky"); this.skyRenderer.extractRenderState(this.level, deltaPartialTick, camera, this.levelRenderState.skyRenderState); profiler.popPush("border"); this.worldBorderRenderer.extract(this.level.getWorldBorder(), deltaPartialTick, cameraPos, this.minecraft.options.getEffectiveRenderDistance() * 16, this.levelRenderState.worldBorderRenderState); profiler.pop(); profiler.popPush("debug"); this.debugRenderer.emitGizmos(frustum, cameraPos.x, cameraPos.y, cameraPos.z, deltaTracker.getGameTimeDeltaPartialTick(false)); this.gameTestBlockHighlightRenderer.emitGizmos(); profiler.popPush("setupFrameGraph"); Matrix4fStack modelViewStack = RenderSystem.getModelViewStack(); modelViewStack.pushMatrix(); modelViewStack.mul((Matrix4fc)modelViewMatrix); FrameGraphBuilder frame = new FrameGraphBuilder(); this.targets.main = frame.importExternal("main", this.minecraft.getMainRenderTarget()); int screenWidth = this.minecraft.getMainRenderTarget().width; int screenHeight = this.minecraft.getMainRenderTarget().height; RenderTargetDescriptor screenSizeTargetDescriptor = new RenderTargetDescriptor(screenWidth, screenHeight, true, 0); PostChain transparencyChain = this.getTransparencyChain(); if (transparencyChain != null) { this.targets.translucent = frame.createInternal("translucent", screenSizeTargetDescriptor); this.targets.itemEntity = frame.createInternal("item_entity", screenSizeTargetDescriptor); this.targets.particles = frame.createInternal("particles", screenSizeTargetDescriptor); this.targets.weather = frame.createInternal("weather", screenSizeTargetDescriptor); this.targets.clouds = frame.createInternal("clouds", screenSizeTargetDescriptor); } if (this.entityOutlineTarget != null) { this.targets.entityOutline = frame.importExternal("entity_outline", this.entityOutlineTarget); } FramePass clearPass = frame.addPass("clear"); this.targets.main = clearPass.readsAndWrites(this.targets.main); clearPass.executes(() -> { RenderTarget mainRenderTarget = this.minecraft.getMainRenderTarget(); RenderSystem.getDevice().createCommandEncoder().clearColorAndDepthTextures(mainRenderTarget.getColorTexture(), ARGB.colorFromFloat(0.0f, fogColor.x, fogColor.y, fogColor.z), mainRenderTarget.getDepthTexture(), 1.0); }); if (shouldRenderSky) { this.addSkyPass(frame, camera, terrainFog); } this.addMainPass(frame, frustum, modelViewMatrix, terrainFog, renderOutline, this.levelRenderState, deltaTracker, profiler); PostChain entityOutlineChain = this.minecraft.getShaderManager().getPostChain(ENTITY_OUTLINE_POST_CHAIN_ID, LevelTargetBundle.OUTLINE_TARGETS); if (this.levelRenderState.haveGlowingEntities && entityOutlineChain != null) { entityOutlineChain.addToFrame(frame, screenWidth, screenHeight, this.targets); } this.minecraft.particleEngine.extract(this.particlesRenderState, new Frustum(frustum).offset(-3.0f), camera, deltaPartialTick); this.addParticlesPass(frame, terrainFog); CloudStatus cloudsType = this.minecraft.options.getCloudsType(); if (cloudsType != CloudStatus.OFF && ARGB.alpha(cloudColor = camera.attributeProbe().getValue(EnvironmentAttributes.CLOUD_COLOR, deltaPartialTick).intValue()) > 0) { float cloudHeight = camera.attributeProbe().getValue(EnvironmentAttributes.CLOUD_HEIGHT, deltaPartialTick).floatValue(); this.addCloudsPass(frame, cloudsType, this.levelRenderState.cameraRenderState.pos, this.levelRenderState.gameTime, deltaPartialTick, cloudColor, cloudHeight); } this.addWeatherPass(frame, terrainFog); if (transparencyChain != null) { transparencyChain.addToFrame(frame, screenWidth, screenHeight, this.targets); } this.addLateDebugPass(frame, this.levelRenderState.cameraRenderState, terrainFog, modelViewMatrix); profiler.popPush("executeFrameGraph"); frame.execute(resourceAllocator, new FrameGraphBuilder.Inspector(){ @Override public void beforeExecutePass(String name) { profiler.push(name); } @Override public void afterExecutePass(String name) { profiler.pop(); } }); this.targets.clear(); modelViewStack.popMatrix(); profiler.pop(); this.levelRenderState.reset(); } private void addMainPass(FrameGraphBuilder frame, Frustum frustum, Matrix4f modelViewMatrix, GpuBufferSlice terrainFog, boolean renderOutline, LevelRenderState levelRenderState, DeltaTracker deltaTracker, ProfilerFiller profiler) { FramePass pass = frame.addPass("main"); this.targets.main = pass.readsAndWrites(this.targets.main); if (this.targets.translucent != null) { this.targets.translucent = pass.readsAndWrites(this.targets.translucent); } if (this.targets.itemEntity != null) { this.targets.itemEntity = pass.readsAndWrites(this.targets.itemEntity); } if (this.targets.weather != null) { this.targets.weather = pass.readsAndWrites(this.targets.weather); } if (levelRenderState.haveGlowingEntities && this.targets.entityOutline != null) { this.targets.entityOutline = pass.readsAndWrites(this.targets.entityOutline); } ResourceHandle mainTarget = this.targets.main; ResourceHandle translucentTarget = this.targets.translucent; ResourceHandle itemEntityTarget = this.targets.itemEntity; ResourceHandle entityOutlineTarget = this.targets.entityOutline; pass.executes(() -> { RenderSystem.setShaderFog(terrainFog); Vec3 cameraPos = levelRenderState.cameraRenderState.pos; double camX = cameraPos.x(); double camY = cameraPos.y(); double camZ = cameraPos.z(); profiler.push("terrain"); if (this.chunkLayerSampler == null) { this.chunkLayerSampler = RenderSystem.getDevice().createSampler(AddressMode.CLAMP_TO_EDGE, AddressMode.CLAMP_TO_EDGE, FilterMode.LINEAR, FilterMode.LINEAR, this.minecraft.options.maxAnisotropyValue(), OptionalDouble.empty()); } ChunkSectionsToRender chunkSectionsToRender = this.prepareChunkRenders((Matrix4fc)modelViewMatrix, camX, camY, camZ); chunkSectionsToRender.renderGroup(ChunkSectionLayerGroup.OPAQUE, this.chunkLayerSampler); this.minecraft.gameRenderer.getLighting().setupFor(Lighting.Entry.LEVEL); if (itemEntityTarget != null) { ((RenderTarget)itemEntityTarget.get()).copyDepthFrom(this.minecraft.getMainRenderTarget()); } if (this.shouldShowEntityOutlines() && entityOutlineTarget != null) { RenderTarget outlineTarget = (RenderTarget)entityOutlineTarget.get(); RenderSystem.getDevice().createCommandEncoder().clearColorAndDepthTextures(outlineTarget.getColorTexture(), 0, outlineTarget.getDepthTexture(), 1.0); } PoseStack poseStack = new PoseStack(); MultiBufferSource.BufferSource bufferSource = this.renderBuffers.bufferSource(); MultiBufferSource.BufferSource crumblingBufferSource = this.renderBuffers.crumblingBufferSource(); profiler.popPush("submitEntities"); this.submitEntities(poseStack, levelRenderState, this.submitNodeStorage); profiler.popPush("submitBlockEntities"); this.submitBlockEntities(poseStack, levelRenderState, this.submitNodeStorage); profiler.popPush("renderFeatures"); this.featureRenderDispatcher.renderAllFeatures(); bufferSource.endLastBatch(); this.checkPoseStack(poseStack); bufferSource.endBatch(RenderTypes.solidMovingBlock()); bufferSource.endBatch(RenderTypes.endPortal()); bufferSource.endBatch(RenderTypes.endGateway()); bufferSource.endBatch(Sheets.solidBlockSheet()); bufferSource.endBatch(Sheets.cutoutBlockSheet()); bufferSource.endBatch(Sheets.bedSheet()); bufferSource.endBatch(Sheets.shulkerBoxSheet()); bufferSource.endBatch(Sheets.signSheet()); bufferSource.endBatch(Sheets.hangingSignSheet()); bufferSource.endBatch(Sheets.chestSheet()); this.renderBuffers.outlineBufferSource().endOutlineBatch(); if (renderOutline) { this.renderBlockOutline(bufferSource, poseStack, false, levelRenderState); } profiler.pop(); this.checkPoseStack(poseStack); bufferSource.endBatch(Sheets.translucentItemSheet()); bufferSource.endBatch(Sheets.bannerSheet()); bufferSource.endBatch(Sheets.shieldSheet()); bufferSource.endBatch(RenderTypes.armorEntityGlint()); bufferSource.endBatch(RenderTypes.glint()); bufferSource.endBatch(RenderTypes.glintTranslucent()); bufferSource.endBatch(RenderTypes.entityGlint()); profiler.push("destroyProgress"); this.renderBlockDestroyAnimation(poseStack, crumblingBufferSource, levelRenderState); crumblingBufferSource.endBatch(); profiler.pop(); this.checkPoseStack(poseStack); bufferSource.endBatch(RenderTypes.waterMask()); bufferSource.endBatch(); if (translucentTarget != null) { ((RenderTarget)translucentTarget.get()).copyDepthFrom((RenderTarget)mainTarget.get()); } profiler.push("translucent"); chunkSectionsToRender.renderGroup(ChunkSectionLayerGroup.TRANSLUCENT, this.chunkLayerSampler); profiler.popPush("string"); chunkSectionsToRender.renderGroup(ChunkSectionLayerGroup.TRIPWIRE, this.chunkLayerSampler); if (renderOutline) { this.renderBlockOutline(bufferSource, poseStack, true, levelRenderState); } bufferSource.endBatch(); profiler.pop(); }); } private void addParticlesPass(FrameGraphBuilder frame, GpuBufferSlice fog) { FramePass pass = frame.addPass("particles"); if (this.targets.particles != null) { this.targets.particles = pass.readsAndWrites(this.targets.particles); pass.reads(this.targets.main); } else { this.targets.main = pass.readsAndWrites(this.targets.main); } ResourceHandle mainTarget = this.targets.main; ResourceHandle particlesTarget = this.targets.particles; pass.executes(() -> { RenderSystem.setShaderFog(fog); if (particlesTarget != null) { ((RenderTarget)particlesTarget.get()).copyDepthFrom((RenderTarget)mainTarget.get()); } this.particlesRenderState.submit(this.submitNodeStorage, this.levelRenderState.cameraRenderState); this.featureRenderDispatcher.renderAllFeatures(); this.particlesRenderState.reset(); }); } private void addCloudsPass(FrameGraphBuilder frame, CloudStatus cloudsType, Vec3 cameraPosition, long gameTime, float partialTicks, int cloudColor, float cloudHeight) { FramePass pass = frame.addPass("clouds"); if (this.targets.clouds != null) { this.targets.clouds = pass.readsAndWrites(this.targets.clouds); } else { this.targets.main = pass.readsAndWrites(this.targets.main); } pass.executes(() -> this.cloudRenderer.render(cloudColor, cloudsType, cloudHeight, cameraPosition, gameTime, partialTicks)); } private void addWeatherPass(FrameGraphBuilder frame, GpuBufferSlice fog) { int renderDistance = this.minecraft.options.getEffectiveRenderDistance() * 16; float depthFar = this.minecraft.gameRenderer.getDepthFar(); FramePass pass = frame.addPass("weather"); if (this.targets.weather != null) { this.targets.weather = pass.readsAndWrites(this.targets.weather); } else { this.targets.main = pass.readsAndWrites(this.targets.main); } pass.executes(() -> { RenderSystem.setShaderFog(fog); MultiBufferSource.BufferSource bufferSource = this.renderBuffers.bufferSource(); CameraRenderState cameraState = this.levelRenderState.cameraRenderState; this.weatherEffectRenderer.render(bufferSource, cameraState.pos, this.levelRenderState.weatherRenderState); this.worldBorderRenderer.render(this.levelRenderState.worldBorderRenderState, cameraState.pos, renderDistance, depthFar); bufferSource.endBatch(); }); } private void addLateDebugPass(FrameGraphBuilder frame, CameraRenderState camera, GpuBufferSlice fog, Matrix4f modelViewMatrix) { FramePass pass = frame.addPass("late_debug"); this.targets.main = pass.readsAndWrites(this.targets.main); if (this.targets.itemEntity != null) { this.targets.itemEntity = pass.readsAndWrites(this.targets.itemEntity); } ResourceHandle mainTarget = this.targets.main; pass.executes(() -> { RenderSystem.setShaderFog(fog); PoseStack poseStack = new PoseStack(); MultiBufferSource.BufferSource bufferSource = this.renderBuffers.bufferSource(); RenderSystem.outputColorTextureOverride = ((RenderTarget)mainTarget.get()).getColorTextureView(); RenderSystem.outputDepthTextureOverride = ((RenderTarget)mainTarget.get()).getDepthTextureView(); DrawableGizmoPrimitives standardPrimitives = new DrawableGizmoPrimitives(); DrawableGizmoPrimitives alwaysOnTopPrimitives = new DrawableGizmoPrimitives(); boolean hasAlwaysOnTop = false; this.collectedGizmos.addTemporaryGizmos(this.minecraft.getPerTickGizmos()); IntegratedServer server = this.minecraft.getSingleplayerServer(); if (server != null) { this.collectedGizmos.addTemporaryGizmos(server.getPerTickGizmos()); } long currentMillis = Util.getMillis(); for (SimpleGizmoCollector.GizmoInstance instance : this.collectedGizmos.drainGizmos()) { float alphaMultiplier = instance.getAlphaMultiplier(currentMillis); if (instance.isAlwaysOnTop()) { hasAlwaysOnTop = true; instance.gizmo().emit(alwaysOnTopPrimitives, alphaMultiplier); continue; } instance.gizmo().emit(standardPrimitives, alphaMultiplier); } standardPrimitives.render(poseStack, bufferSource, camera, modelViewMatrix); bufferSource.endLastBatch(); if (hasAlwaysOnTop) { RenderTarget mainRenderTarget = Minecraft.getInstance().getMainRenderTarget(); RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(mainRenderTarget.getDepthTexture(), 1.0); alwaysOnTopPrimitives.render(poseStack, bufferSource, camera, modelViewMatrix); bufferSource.endLastBatch(); } RenderSystem.outputColorTextureOverride = null; RenderSystem.outputDepthTextureOverride = null; this.checkPoseStack(poseStack); }); } private void extractVisibleEntities(Camera camera, Frustum frustum, DeltaTracker deltaTracker, LevelRenderState output) { Vec3 cameraPos = camera.position(); double camX = cameraPos.x(); double camY = cameraPos.y(); double camZ = cameraPos.z(); TickRateManager tickRateManager = this.minecraft.level.tickRateManager(); boolean shouldShowEntityOutlines = this.shouldShowEntityOutlines(); Entity.setViewScale(Mth.clamp((double)this.minecraft.options.getEffectiveRenderDistance() / 8.0, 1.0, 2.5) * this.minecraft.options.entityDistanceScaling().get()); for (Entity entity : this.level.entitiesForRendering()) { BlockPos blockPos; if (!this.entityRenderDispatcher.shouldRender(entity, frustum, camX, camY, camZ) && !entity.hasIndirectPassenger(this.minecraft.player) || !this.level.isOutsideBuildHeight((blockPos = entity.blockPosition()).getY()) && !this.isSectionCompiledAndVisible(blockPos) || entity == camera.entity() && !camera.isDetached() && (!(camera.entity() instanceof LivingEntity) || !((LivingEntity)camera.entity()).isSleeping()) || entity instanceof LocalPlayer && camera.entity() != entity) continue; if (entity.tickCount == 0) { entity.xOld = entity.getX(); entity.yOld = entity.getY(); entity.zOld = entity.getZ(); } float partialEntity = deltaTracker.getGameTimeDeltaPartialTick(!tickRateManager.isEntityFrozen(entity)); EntityRenderState state = this.extractEntity(entity, partialEntity); output.entityRenderStates.add(state); if (!state.appearsGlowing() || !shouldShowEntityOutlines) continue; output.haveGlowingEntities = true; } } private void submitEntities(PoseStack poseStack, LevelRenderState levelRenderState, SubmitNodeCollector output) { Vec3 cameraPos = levelRenderState.cameraRenderState.pos; double camX = cameraPos.x(); double camY = cameraPos.y(); double camZ = cameraPos.z(); for (EntityRenderState state : levelRenderState.entityRenderStates) { if (!levelRenderState.haveGlowingEntities) { state.outlineColor = 0; } this.entityRenderDispatcher.submit(state, levelRenderState.cameraRenderState, state.x - camX, state.y - camY, state.z - camZ, poseStack, output); } } private void extractVisibleBlockEntities(Camera camera, float deltaPartialTick, LevelRenderState levelRenderState) { Vec3 cameraPos = camera.position(); double camX = cameraPos.x(); double camY = cameraPos.y(); double camZ = cameraPos.z(); PoseStack poseStack = new PoseStack(); for (SectionRenderDispatcher.RenderSection section : this.visibleSections) { List renderableBlockEntities = section.getSectionMesh().getRenderableBlockEntities(); if (renderableBlockEntities.isEmpty()) continue; for (BlockEntity blockEntity : renderableBlockEntities) { Object state; ModelFeatureRenderer.CrumblingOverlay breakProgress; BlockPos blockPos = blockEntity.getBlockPos(); SortedSet progresses = (SortedSet)this.destructionProgress.get(blockPos.asLong()); if (progresses == null || progresses.isEmpty()) { breakProgress = null; } else { poseStack.pushPose(); poseStack.translate((double)blockPos.getX() - camX, (double)blockPos.getY() - camY, (double)blockPos.getZ() - camZ); breakProgress = new ModelFeatureRenderer.CrumblingOverlay(((BlockDestructionProgress)progresses.last()).getProgress(), poseStack.last()); poseStack.popPose(); } if ((state = this.blockEntityRenderDispatcher.tryExtractRenderState(blockEntity, deltaPartialTick, breakProgress)) == null) continue; levelRenderState.blockEntityRenderStates.add((BlockEntityRenderState)state); } } Iterator iterator = this.level.getGloballyRenderedBlockEntities().iterator(); while (iterator.hasNext()) { BlockEntity blockEntity = iterator.next(); if (blockEntity.isRemoved()) { iterator.remove(); continue; } Object state = this.blockEntityRenderDispatcher.tryExtractRenderState(blockEntity, deltaPartialTick, null); if (state == null) continue; levelRenderState.blockEntityRenderStates.add((BlockEntityRenderState)state); } } private void submitBlockEntities(PoseStack poseStack, LevelRenderState levelRenderState, SubmitNodeStorage submitNodeStorage) { Vec3 cameraPos = levelRenderState.cameraRenderState.pos; double camX = cameraPos.x(); double camY = cameraPos.y(); double camZ = cameraPos.z(); for (BlockEntityRenderState renderState : levelRenderState.blockEntityRenderStates) { BlockPos blockPos = renderState.blockPos; poseStack.pushPose(); poseStack.translate((double)blockPos.getX() - camX, (double)blockPos.getY() - camY, (double)blockPos.getZ() - camZ); this.blockEntityRenderDispatcher.submit(renderState, poseStack, submitNodeStorage, levelRenderState.cameraRenderState); poseStack.popPose(); } } private void extractBlockDestroyAnimation(Camera camera, LevelRenderState levelRenderState) { Vec3 cameraPos = camera.position(); double camX = cameraPos.x(); double camY = cameraPos.y(); double camZ = cameraPos.z(); levelRenderState.blockBreakingRenderStates.clear(); for (Long2ObjectMap.Entry entry : this.destructionProgress.long2ObjectEntrySet()) { SortedSet progresses; BlockPos pos = BlockPos.of(entry.getLongKey()); if (pos.distToCenterSqr(camX, camY, camZ) > 1024.0 || (progresses = (SortedSet)entry.getValue()) == null || progresses.isEmpty()) continue; int progress = ((BlockDestructionProgress)progresses.last()).getProgress(); levelRenderState.blockBreakingRenderStates.add(new BlockBreakingRenderState(this.level, pos, progress)); } } private void renderBlockDestroyAnimation(PoseStack poseStack, MultiBufferSource.BufferSource bufferSource, LevelRenderState levelRenderState) { Vec3 cameraPos = levelRenderState.cameraRenderState.pos; double camX = cameraPos.x(); double camY = cameraPos.y(); double camZ = cameraPos.z(); for (BlockBreakingRenderState state : levelRenderState.blockBreakingRenderStates) { poseStack.pushPose(); BlockPos pos = state.blockPos; poseStack.translate((double)pos.getX() - camX, (double)pos.getY() - camY, (double)pos.getZ() - camZ); PoseStack.Pose cameraPose = poseStack.last(); SheetedDecalTextureGenerator buffer = new SheetedDecalTextureGenerator(bufferSource.getBuffer(ModelBakery.DESTROY_TYPES.get(state.progress)), cameraPose, 1.0f); this.minecraft.getBlockRenderer().renderBreakingTexture(state.blockState, pos, state, poseStack, buffer); poseStack.popPose(); } } private void extractBlockOutline(Camera camera, LevelRenderState levelRenderState) { levelRenderState.blockOutlineRenderState = null; HitResult hitResult = this.minecraft.hitResult; if (!(hitResult instanceof BlockHitResult)) { return; } BlockHitResult blockHitResult = (BlockHitResult)hitResult; if (blockHitResult.getType() == HitResult.Type.MISS) { return; } BlockPos pos = blockHitResult.getBlockPos(); BlockState state = this.level.getBlockState(pos); if (!state.isAir() && this.level.getWorldBorder().isWithinBounds(pos)) { boolean isBlockTranslucent = ItemBlockRenderTypes.getChunkRenderType(state).sortOnUpload(); boolean highContrast = this.minecraft.options.highContrastBlockOutline().get(); CollisionContext context = CollisionContext.of(camera.entity()); VoxelShape shape = state.getShape(this.level, pos, context); if (SharedConstants.DEBUG_SHAPES) { VoxelShape collisionShape = state.getCollisionShape(this.level, pos, context); VoxelShape occlusionShape = state.getOcclusionShape(); VoxelShape interactionShape = state.getInteractionShape(this.level, pos); levelRenderState.blockOutlineRenderState = new BlockOutlineRenderState(pos, isBlockTranslucent, highContrast, shape, collisionShape, occlusionShape, interactionShape); } else { levelRenderState.blockOutlineRenderState = new BlockOutlineRenderState(pos, isBlockTranslucent, highContrast, shape); } } } private void renderBlockOutline(MultiBufferSource.BufferSource bufferSource, PoseStack poseStack, boolean onlyTranslucentBlocks, LevelRenderState levelRenderState) { VertexConsumer buffer; BlockOutlineRenderState state = levelRenderState.blockOutlineRenderState; if (state == null) { return; } if (state.isTranslucent() != onlyTranslucentBlocks) { return; } Vec3 cameraPos = levelRenderState.cameraRenderState.pos; if (state.highContrast()) { buffer = bufferSource.getBuffer(RenderTypes.secondaryBlockOutline()); this.renderHitOutline(poseStack, buffer, cameraPos.x, cameraPos.y, cameraPos.z, state, -16777216, 7.0f); } buffer = bufferSource.getBuffer(RenderTypes.lines()); int outlineColor = state.highContrast() ? -11010079 : ARGB.black(102); this.renderHitOutline(poseStack, buffer, cameraPos.x, cameraPos.y, cameraPos.z, state, outlineColor, this.minecraft.getWindow().getAppropriateLineWidth()); bufferSource.endLastBatch(); } private void checkPoseStack(PoseStack poseStack) { if (!poseStack.isEmpty()) { throw new IllegalStateException("Pose stack not empty"); } } private EntityRenderState extractEntity(Entity entity, float partialTickTime) { return this.entityRenderDispatcher.extractEntity(entity, partialTickTime); } private void scheduleTranslucentSectionResort(Vec3 cameraPos) { if (this.visibleSections.isEmpty()) { return; } BlockPos cameraBlockPos = BlockPos.containing(cameraPos); boolean blockPosChanged = !cameraBlockPos.equals(this.lastTranslucentSortBlockPos); TranslucencyPointOfView pointOfView = new TranslucencyPointOfView(); for (SectionRenderDispatcher.RenderSection section : this.nearbyVisibleSections) { this.scheduleResort(section, pointOfView, cameraPos, blockPosChanged, true); } this.translucencyResortIterationIndex %= this.visibleSections.size(); int resortsLeft = Math.max(this.visibleSections.size() / 8, 15); while (resortsLeft-- > 0) { int index = this.translucencyResortIterationIndex++ % this.visibleSections.size(); this.scheduleResort((SectionRenderDispatcher.RenderSection)this.visibleSections.get(index), pointOfView, cameraPos, blockPosChanged, false); } this.lastTranslucentSortBlockPos = cameraBlockPos; } private void scheduleResort(SectionRenderDispatcher.RenderSection section, TranslucencyPointOfView pointOfView, Vec3 cameraPos, boolean blockPosChanged, boolean isNearby) { boolean resortBecauseBlockPosChanged; pointOfView.set(cameraPos, section.getSectionNode()); boolean pointOfViewChanged = section.getSectionMesh().isDifferentPointOfView(pointOfView); boolean bl = resortBecauseBlockPosChanged = blockPosChanged && (pointOfView.isAxisAligned() || isNearby); if ((resortBecauseBlockPosChanged || pointOfViewChanged) && !section.transparencyResortingScheduled() && section.hasTranslucentGeometry()) { section.resortTransparency(this.sectionRenderDispatcher); } } private ChunkSectionsToRender prepareChunkRenders(Matrix4fc modelViewMatrix, double camX, double camY, double camZ) { ObjectListIterator iterator = this.visibleSections.listIterator(0); EnumMap>> drawsByLayer = new EnumMap>>(ChunkSectionLayer.class); int largestIndexCount = 0; for (ChunkSectionLayer layer : ChunkSectionLayer.values()) { drawsByLayer.put(layer, new ArrayList()); } ArrayList sectionInfos = new ArrayList(); GpuTextureView blockAtlas = this.minecraft.getTextureManager().getTexture(TextureAtlas.LOCATION_BLOCKS).getTextureView(); int textureAtlasWidth = blockAtlas.getWidth(0); int textureAtlasHeight = blockAtlas.getHeight(0); while (iterator.hasNext()) { SectionRenderDispatcher.RenderSection section = (SectionRenderDispatcher.RenderSection)iterator.next(); SectionMesh sectionMesh = section.getSectionMesh(); BlockPos renderOffset = section.getRenderOrigin(); long now = Util.getMillis(); int uboIndex = -1; for (ChunkSectionLayer layer : ChunkSectionLayer.values()) { VertexFormat.IndexType indexType; GpuBuffer indexBuffer; SectionBuffers buffers = sectionMesh.getBuffers(layer); if (buffers == null) continue; if (uboIndex == -1) { uboIndex = sectionInfos.size(); sectionInfos.add(new DynamicUniforms.ChunkSectionInfo((Matrix4fc)new Matrix4f(modelViewMatrix), renderOffset.getX(), renderOffset.getY(), renderOffset.getZ(), section.getVisibility(now), textureAtlasWidth, textureAtlasHeight)); } if (buffers.getIndexBuffer() == null) { if (buffers.getIndexCount() > largestIndexCount) { largestIndexCount = buffers.getIndexCount(); } indexBuffer = null; indexType = null; } else { indexBuffer = buffers.getIndexBuffer(); indexType = buffers.getIndexType(); } int finalUboIndex = uboIndex; drawsByLayer.get((Object)layer).add(new RenderPass.Draw(0, buffers.getVertexBuffer(), indexBuffer, indexType, 0, buffers.getIndexCount(), (sectionUbos, uploader) -> uploader.upload("ChunkSection", sectionUbos[finalUboIndex]))); } } GpuBufferSlice[] chunkSectionInfos = RenderSystem.getDynamicUniforms().writeChunkSections(sectionInfos.toArray(new DynamicUniforms.ChunkSectionInfo[0])); return new ChunkSectionsToRender(blockAtlas, drawsByLayer, largestIndexCount, chunkSectionInfos); } public void endFrame() { this.cloudRenderer.endFrame(); } public void captureFrustum() { this.captureFrustum = true; } public void killFrustum() { this.capturedFrustum = null; } public void tick(Camera camera) { if (this.level.tickRateManager().runsNormally()) { ++this.ticks; } this.weatherEffectRenderer.tickRainParticles(this.level, camera, this.ticks, this.minecraft.options.particles().get(), this.minecraft.options.weatherRadius().get()); this.removeBlockBreakingProgress(); } private void removeBlockBreakingProgress() { if (this.ticks % 20 != 0) { return; } ObjectIterator iterator = this.destroyingBlocks.values().iterator(); while (iterator.hasNext()) { BlockDestructionProgress block = (BlockDestructionProgress)iterator.next(); int updatedRenderTick = block.getUpdatedRenderTick(); if (this.ticks - updatedRenderTick <= 400) continue; iterator.remove(); this.removeProgress(block); } } private void removeProgress(BlockDestructionProgress block) { long pos = block.getPos().asLong(); Set progresses = (Set)this.destructionProgress.get(pos); progresses.remove(block); if (progresses.isEmpty()) { this.destructionProgress.remove(pos); } } private void addSkyPass(FrameGraphBuilder frame, Camera camera, GpuBufferSlice skyFog) { FogType fogType = camera.getFluidInCamera(); if (fogType == FogType.POWDER_SNOW || fogType == FogType.LAVA || this.doesMobEffectBlockSky(camera)) { return; } SkyRenderState state = this.levelRenderState.skyRenderState; if (state.skybox == DimensionType.Skybox.NONE) { return; } SkyRenderer skyRenderer = this.skyRenderer; if (skyRenderer == null) { return; } FramePass pass = frame.addPass("sky"); this.targets.main = pass.readsAndWrites(this.targets.main); pass.executes(() -> { RenderSystem.setShaderFog(skyFog); if (state.skybox == DimensionType.Skybox.END) { skyRenderer.renderEndSky(); if (state.endFlashIntensity > 1.0E-5f) { PoseStack poseStack = new PoseStack(); skyRenderer.renderEndFlash(poseStack, state.endFlashIntensity, state.endFlashXAngle, state.endFlashYAngle); } return; } PoseStack poseStack = new PoseStack(); skyRenderer.renderSkyDisc(state.skyColor); skyRenderer.renderSunriseAndSunset(poseStack, state.sunAngle, state.sunriseAndSunsetColor); skyRenderer.renderSunMoonAndStars(poseStack, state.sunAngle, state.moonAngle, state.starAngle, state.moonPhase, state.rainBrightness, state.starBrightness); if (state.shouldRenderDarkDisc) { skyRenderer.renderDarkDisc(); } }); } private boolean doesMobEffectBlockSky(Camera camera) { Entity entity = camera.entity(); if (entity instanceof LivingEntity) { LivingEntity livingEntity = (LivingEntity)entity; return livingEntity.hasEffect(MobEffects.BLINDNESS) || livingEntity.hasEffect(MobEffects.DARKNESS); } return false; } private void compileSections(Camera camera) { ProfilerFiller profiler = Profiler.get(); profiler.push("populateSectionsToCompile"); RenderRegionCache cache = new RenderRegionCache(); BlockPos cameraPosition = camera.blockPosition(); ArrayList sectionsToCompile = Lists.newArrayList(); long fadeDuration = Mth.floor(this.minecraft.options.chunkSectionFadeInTime().get() * 1000.0); for (SectionRenderDispatcher.RenderSection section : this.visibleSections) { if (!section.isDirty() || section.getSectionMesh() == CompiledSectionMesh.UNCOMPILED && !section.hasAllNeighbors()) continue; BlockPos center = SectionPos.of(section.getSectionNode()).center(); double distSqr = center.distSqr(cameraPosition); boolean isNearby = distSqr < 768.0; boolean rebuildSync = false; if (this.minecraft.options.prioritizeChunkUpdates().get() == PrioritizeChunkUpdates.NEARBY) { rebuildSync = isNearby || section.isDirtyFromPlayer(); } else if (this.minecraft.options.prioritizeChunkUpdates().get() == PrioritizeChunkUpdates.PLAYER_AFFECTED) { rebuildSync = section.isDirtyFromPlayer(); } if (isNearby || section.wasPreviouslyEmpty()) { section.setFadeDuration(0L); } else { section.setFadeDuration(fadeDuration); } section.setWasPreviouslyEmpty(false); if (rebuildSync) { profiler.push("compileSectionSynchronously"); this.sectionRenderDispatcher.rebuildSectionSync(section, cache); section.setNotDirty(); profiler.pop(); continue; } sectionsToCompile.add(section); } profiler.popPush("uploadSectionMeshes"); this.sectionRenderDispatcher.uploadAllPendingUploads(); profiler.popPush("scheduleAsyncCompile"); for (SectionRenderDispatcher.RenderSection renderSection : sectionsToCompile) { renderSection.rebuildSectionAsync(cache); renderSection.setNotDirty(); } profiler.popPush("scheduleTranslucentResort"); this.scheduleTranslucentSectionResort(camera.position()); profiler.pop(); } private void renderHitOutline(PoseStack poseStack, VertexConsumer builder, double camX, double camY, double camZ, BlockOutlineRenderState state, int color, float width) { BlockPos pos = state.pos(); if (SharedConstants.DEBUG_SHAPES) { ShapeRenderer.renderShape(poseStack, builder, state.shape(), (double)pos.getX() - camX, (double)pos.getY() - camY, (double)pos.getZ() - camZ, ARGB.colorFromFloat(1.0f, 1.0f, 1.0f, 1.0f), width); if (state.collisionShape() != null) { ShapeRenderer.renderShape(poseStack, builder, state.collisionShape(), (double)pos.getX() - camX, (double)pos.getY() - camY, (double)pos.getZ() - camZ, ARGB.colorFromFloat(0.4f, 0.0f, 0.0f, 0.0f), width); } if (state.occlusionShape() != null) { ShapeRenderer.renderShape(poseStack, builder, state.occlusionShape(), (double)pos.getX() - camX, (double)pos.getY() - camY, (double)pos.getZ() - camZ, ARGB.colorFromFloat(0.4f, 0.0f, 1.0f, 0.0f), width); } if (state.interactionShape() != null) { ShapeRenderer.renderShape(poseStack, builder, state.interactionShape(), (double)pos.getX() - camX, (double)pos.getY() - camY, (double)pos.getZ() - camZ, ARGB.colorFromFloat(0.4f, 0.0f, 0.0f, 1.0f), width); } } else { ShapeRenderer.renderShape(poseStack, builder, state.shape(), (double)pos.getX() - camX, (double)pos.getY() - camY, (double)pos.getZ() - camZ, color, width); } } public void blockChanged(BlockGetter level, BlockPos pos, BlockState old, BlockState current, int updateFlags) { this.setBlockDirty(pos, (updateFlags & 8) != 0); } private void setBlockDirty(BlockPos pos, boolean playerChanged) { for (int z = pos.getZ() - 1; z <= pos.getZ() + 1; ++z) { for (int x = pos.getX() - 1; x <= pos.getX() + 1; ++x) { for (int y = pos.getY() - 1; y <= pos.getY() + 1; ++y) { this.setSectionDirty(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(y), SectionPos.blockToSectionCoord(z), playerChanged); } } } } public void setBlocksDirty(int x0, int y0, int z0, int x1, int y1, int z1) { for (int z = z0 - 1; z <= z1 + 1; ++z) { for (int x = x0 - 1; x <= x1 + 1; ++x) { for (int y = y0 - 1; y <= y1 + 1; ++y) { this.setSectionDirty(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(y), SectionPos.blockToSectionCoord(z)); } } } } public void setBlockDirty(BlockPos pos, BlockState oldState, BlockState newState) { if (this.minecraft.getModelManager().requiresRender(oldState, newState)) { this.setBlocksDirty(pos.getX(), pos.getY(), pos.getZ(), pos.getX(), pos.getY(), pos.getZ()); } } public void setSectionDirtyWithNeighbors(int sectionX, int sectionY, int sectionZ) { this.setSectionRangeDirty(sectionX - 1, sectionY - 1, sectionZ - 1, sectionX + 1, sectionY + 1, sectionZ + 1); } public void setSectionRangeDirty(int minSectionX, int minSectionY, int minSectionZ, int maxSectionX, int maxSectionY, int maxSectionZ) { for (int z = minSectionZ; z <= maxSectionZ; ++z) { for (int x = minSectionX; x <= maxSectionX; ++x) { for (int y = minSectionY; y <= maxSectionY; ++y) { this.setSectionDirty(x, y, z); } } } } public void setSectionDirty(int sectionX, int sectionY, int sectionZ) { this.setSectionDirty(sectionX, sectionY, sectionZ, false); } private void setSectionDirty(int sectionX, int sectionY, int sectionZ, boolean playerChanged) { this.viewArea.setDirty(sectionX, sectionY, sectionZ, playerChanged); } public void onSectionBecomingNonEmpty(long sectionNode) { SectionRenderDispatcher.RenderSection section = this.viewArea.getRenderSection(sectionNode); if (section != null) { this.sectionOcclusionGraph.schedulePropagationFrom(section); section.setWasPreviouslyEmpty(true); } } public void destroyBlockProgress(int id, BlockPos pos, int progress) { if (progress < 0 || progress >= 10) { BlockDestructionProgress removed = (BlockDestructionProgress)this.destroyingBlocks.remove(id); if (removed != null) { this.removeProgress(removed); } } else { BlockDestructionProgress entry = (BlockDestructionProgress)this.destroyingBlocks.get(id); if (entry != null) { this.removeProgress(entry); } if (entry == null || entry.getPos().getX() != pos.getX() || entry.getPos().getY() != pos.getY() || entry.getPos().getZ() != pos.getZ()) { entry = new BlockDestructionProgress(id, pos); this.destroyingBlocks.put(id, (Object)entry); } entry.setProgress(progress); entry.updateTick(this.ticks); ((SortedSet)this.destructionProgress.computeIfAbsent(entry.getPos().asLong(), k -> Sets.newTreeSet())).add(entry); } } public boolean hasRenderedAllSections() { return this.sectionRenderDispatcher.isQueueEmpty(); } public void onChunkReadyToRender(ChunkPos pos) { this.sectionOcclusionGraph.onChunkReadyToRender(pos); } public void needsUpdate() { this.sectionOcclusionGraph.invalidate(); this.cloudRenderer.markForRebuild(); } public static int getLightColor(BlockAndTintGetter level, BlockPos pos) { return LevelRenderer.getLightColor(BrightnessGetter.DEFAULT, level, level.getBlockState(pos), pos); } public static int getLightColor(BrightnessGetter brightnessGetter, BlockAndTintGetter level, BlockState state, BlockPos pos) { int blockSelfEmission; if (state.emissiveRendering(level, pos)) { return 0xF000F0; } int packedBrightness = brightnessGetter.packedBrightness(level, pos); int block = LightTexture.block(packedBrightness); if (block < (blockSelfEmission = state.getLightEmission())) { int sky = LightTexture.sky(packedBrightness); return LightTexture.pack(blockSelfEmission, sky); } return packedBrightness; } public boolean isSectionCompiledAndVisible(BlockPos blockPos) { SectionRenderDispatcher.RenderSection renderSection = this.viewArea.getRenderSectionAt(blockPos); if (renderSection == null || renderSection.sectionMesh.get() == CompiledSectionMesh.UNCOMPILED) { return false; } return renderSection.getVisibility(Util.getMillis()) >= 0.3f; } public @Nullable RenderTarget entityOutlineTarget() { return this.targets.entityOutline != null ? this.targets.entityOutline.get() : null; } public @Nullable RenderTarget getTranslucentTarget() { return this.targets.translucent != null ? this.targets.translucent.get() : null; } public @Nullable RenderTarget getItemEntityTarget() { return this.targets.itemEntity != null ? this.targets.itemEntity.get() : null; } public @Nullable RenderTarget getParticlesTarget() { return this.targets.particles != null ? this.targets.particles.get() : null; } public @Nullable RenderTarget getWeatherTarget() { return this.targets.weather != null ? this.targets.weather.get() : null; } public @Nullable RenderTarget getCloudsTarget() { return this.targets.clouds != null ? this.targets.clouds.get() : null; } @VisibleForDebug public ObjectArrayList getVisibleSections() { return this.visibleSections; } @VisibleForDebug public SectionOcclusionGraph getSectionOcclusionGraph() { return this.sectionOcclusionGraph; } public @Nullable Frustum getCapturedFrustum() { return this.capturedFrustum; } public CloudRenderer getCloudRenderer() { return this.cloudRenderer; } public Gizmos.TemporaryCollection collectPerFrameGizmos() { return Gizmos.withCollector(this.collectedGizmos); } @FunctionalInterface public static interface BrightnessGetter { public static final BrightnessGetter DEFAULT = (level, pos) -> { int sky = level.getBrightness(LightLayer.SKY, pos); int block = level.getBrightness(LightLayer.BLOCK, pos); return Brightness.pack(block, sky); }; public int packedBrightness(BlockAndTintGetter var1, BlockPos var2); } }