LevelRenderer.java

net.minecraft.client.renderer.LevelRenderer

信息

  • 全限定名:net.minecraft.client.renderer.LevelRenderer
  • 类型:public class
  • 包:net.minecraft.client.renderer
  • 源码路径:src/main/java/net/minecraft/client/renderer/LevelRenderer.java
  • 起始行号:L127
  • 实现:ResourceManagerReloadListener, AutoCloseable
  • 职责:

    TODO

字段/常量

  • TRANSPARENCY_POST_CHAIN_ID

    • 类型: Identifier
    • 修饰符: private static final
    • 源码定位: L128
    • 说明:

      TODO

  • ENTITY_OUTLINE_POST_CHAIN_ID

    • 类型: Identifier
    • 修饰符: private static final
    • 源码定位: L129
    • 说明:

      TODO

  • SECTION_SIZE

    • 类型: int
    • 修饰符: public static final
    • 源码定位: L130
    • 说明:

      TODO

  • HALF_SECTION_SIZE

    • 类型: int
    • 修饰符: public static final
    • 源码定位: L131
    • 说明:

      TODO

  • NEARBY_SECTION_DISTANCE_IN_BLOCKS

    • 类型: int
    • 修饰符: public static final
    • 源码定位: L132
    • 说明:

      TODO

  • MINIMUM_TRANSPARENT_SORT_COUNT

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L133
    • 说明:

      TODO

  • CHUNK_VISIBILITY_THRESHOLD

    • 类型: float
    • 修饰符: private static final
    • 源码定位: L134
    • 说明:

      TODO

  • minecraft

    • 类型: Minecraft
    • 修饰符: private final
    • 源码定位: L135
    • 说明:

      TODO

  • entityRenderDispatcher

    • 类型: EntityRenderDispatcher
    • 修饰符: private final
    • 源码定位: L136
    • 说明:

      TODO

  • blockEntityRenderDispatcher

    • 类型: BlockEntityRenderDispatcher
    • 修饰符: private final
    • 源码定位: L137
    • 说明:

      TODO

  • renderBuffers

    • 类型: RenderBuffers
    • 修饰符: private final
    • 源码定位: L138
    • 说明:

      TODO

  • skyRenderer

    • 类型: SkyRenderer
    • 修饰符: private
    • 源码定位: L139
    • 说明:

      TODO

  • cloudRenderer

    • 类型: CloudRenderer
    • 修饰符: private final
    • 源码定位: L140
    • 说明:

      TODO

  • worldBorderRenderer

    • 类型: WorldBorderRenderer
    • 修饰符: private final
    • 源码定位: L141
    • 说明:

      TODO

  • weatherEffectRenderer

    • 类型: WeatherEffectRenderer
    • 修饰符: private final
    • 源码定位: L142
    • 说明:

      TODO

  • debugRenderer

    • 类型: DebugRenderer
    • 修饰符: public final
    • 源码定位: L143
    • 说明:

      TODO

  • gameTestBlockHighlightRenderer

    • 类型: GameTestBlockHighlightRenderer
    • 修饰符: public final
    • 源码定位: L144
    • 说明:

      TODO

  • level

    • 类型: ClientLevel
    • 修饰符: private
    • 源码定位: L145
    • 说明:

      TODO

  • sectionOcclusionGraph

    • 类型: SectionOcclusionGraph
    • 修饰符: private final
    • 源码定位: L146
    • 说明:

      TODO

  • visibleSections

    • 类型: ObjectArrayList<SectionRenderDispatcher.RenderSection>
    • 修饰符: private final
    • 源码定位: L147
    • 说明:

      TODO

  • nearbyVisibleSections

    • 类型: ObjectArrayList<SectionRenderDispatcher.RenderSection>
    • 修饰符: private final
    • 源码定位: L148
    • 说明:

      TODO

  • viewArea

    • 类型: ViewArea
    • 修饰符: private
    • 源码定位: L149
    • 说明:

      TODO

  • ticks

    • 类型: int
    • 修饰符: private
    • 源码定位: L150
    • 说明:

      TODO

  • destroyingBlocks

    • 类型: Int2ObjectMap<BlockDestructionProgress>
    • 修饰符: private final
    • 源码定位: L151
    • 说明:

      TODO

  • destructionProgress

    • 类型: Long2ObjectMap<SortedSet<BlockDestructionProgress>>
    • 修饰符: private final
    • 源码定位: L152
    • 说明:

      TODO

  • entityOutlineTarget

    • 类型: RenderTarget
    • 修饰符: private
    • 源码定位: L153
    • 说明:

      TODO

  • targets

    • 类型: LevelTargetBundle
    • 修饰符: private final
    • 源码定位: L154
    • 说明:

      TODO

  • lastCameraSectionX

    • 类型: int
    • 修饰符: private
    • 源码定位: L155
    • 说明:

      TODO

  • lastCameraSectionY

    • 类型: int
    • 修饰符: private
    • 源码定位: L156
    • 说明:

      TODO

  • lastCameraSectionZ

    • 类型: int
    • 修饰符: private
    • 源码定位: L157
    • 说明:

      TODO

  • prevCamX

    • 类型: double
    • 修饰符: private
    • 源码定位: L158
    • 说明:

      TODO

  • prevCamY

    • 类型: double
    • 修饰符: private
    • 源码定位: L159
    • 说明:

      TODO

  • prevCamZ

    • 类型: double
    • 修饰符: private
    • 源码定位: L160
    • 说明:

      TODO

  • prevCamRotX

    • 类型: double
    • 修饰符: private
    • 源码定位: L161
    • 说明:

      TODO

  • prevCamRotY

    • 类型: double
    • 修饰符: private
    • 源码定位: L162
    • 说明:

      TODO

  • lastSmartCull

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L163
    • 说明:

      TODO

  • sectionRenderDispatcher

    • 类型: SectionRenderDispatcher
    • 修饰符: private
    • 源码定位: L164
    • 说明:

      TODO

  • lastViewDistance

    • 类型: int
    • 修饰符: private
    • 源码定位: L165
    • 说明:

      TODO

  • lastTranslucentSortBlockPos

    • 类型: BlockPos
    • 修饰符: private
    • 源码定位: L166
    • 说明:

      TODO

  • translucencyResortIterationIndex

    • 类型: int
    • 修饰符: private
    • 源码定位: L167
    • 说明:

      TODO

  • optionsRenderState

    • 类型: OptionsRenderState
    • 修饰符: private final
    • 源码定位: L168
    • 说明:

      TODO

  • levelRenderState

    • 类型: LevelRenderState
    • 修饰符: private final
    • 源码定位: L169
    • 说明:

      TODO

  • submitNodeStorage

    • 类型: SubmitNodeStorage
    • 修饰符: private final
    • 源码定位: L170
    • 说明:

      TODO

  • featureRenderDispatcher

    • 类型: FeatureRenderDispatcher
    • 修饰符: private final
    • 源码定位: L171
    • 说明:

      TODO

  • chunkLayerSampler

    • 类型: GpuSampler
    • 修饰符: private
    • 源码定位: L172
    • 说明:

      TODO

  • collectedGizmos

    • 类型: SimpleGizmoCollector
    • 修饰符: private final
    • 源码定位: L173
    • 说明:

      TODO

  • finalizedGizmos

    • 类型: LevelRenderer.FinalizedGizmos
    • 修饰符: private
    • 源码定位: L174
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.client.renderer.LevelRenderer.BrightnessGetter

    • 类型: interface
    • 修饰符: public
    • 源码定位: L1515
    • 说明:

      TODO

  • net.minecraft.client.renderer.LevelRenderer.FinalizedGizmos

    • 类型: record
    • 修饰符: private
    • 源码定位: L1526
    • 说明:

      TODO

构造器

public LevelRenderer(Minecraft minecraft, EntityRenderDispatcher entityRenderDispatcher, BlockEntityRenderDispatcher blockEntityRenderDispatcher, RenderBuffers renderBuffers, GameRenderState gameRenderState, FeatureRenderDispatcher featureRenderDispatcher) @ L176

  • 构造器名:LevelRenderer
  • 源码定位:L176
  • 修饰符:public

参数:

  • minecraft: Minecraft
  • entityRenderDispatcher: EntityRenderDispatcher
  • blockEntityRenderDispatcher: BlockEntityRenderDispatcher
  • renderBuffers: RenderBuffers
  • gameRenderState: GameRenderState
  • featureRenderDispatcher: FeatureRenderDispatcher

说明:

TODO

方法

下面的方法块按源码顺序生成。

public void close() @ L194

  • 方法名:close
  • 源码定位:L194
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public void onResourceManagerReload(ResourceManager resourceManager) @ L211

  • 方法名:onResourceManagerReload
  • 源码定位:L211
  • 返回类型:void
  • 修饰符:public

参数:

  • resourceManager: ResourceManager

说明:

TODO

public void initOutline() @ L221

  • 方法名:initOutline
  • 源码定位:L221
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

private PostChain getTransparencyChain() @ L230

  • 方法名:getTransparencyChain
  • 源码定位:L230
  • 返回类型:PostChain
  • 修饰符:private

参数:

说明:

TODO

public void doEntityOutline() @ L236

  • 方法名:doEntityOutline
  • 源码定位:L236
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

protected boolean shouldShowEntityOutlines() @ L242

  • 方法名:shouldShowEntityOutlines
  • 源码定位:L242
  • 返回类型:boolean
  • 修饰符:protected

参数:

说明:

TODO

public void setLevel(ClientLevel level) @ L246

  • 方法名:setLevel
  • 源码定位:L246
  • 返回类型:void
  • 修饰符:public

参数:

  • level: ClientLevel

说明:

TODO

private void clearVisibleSections() @ L272

  • 方法名:clearVisibleSections
  • 源码定位:L272
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

public void allChanged() @ L277

  • 方法名:allChanged
  • 源码定位:L277
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public void resize(int width, int height) @ L314

  • 方法名:resize
  • 源码定位:L314
  • 返回类型:void
  • 修饰符:public

参数:

  • width: int
  • height: int

说明:

TODO

public String getSectionStatistics() @ L321

  • 方法名:getSectionStatistics
  • 源码定位:L321
  • 返回类型:String
  • 修饰符:public

参数:

说明:

TODO

public SectionRenderDispatcher getSectionRenderDispatcher() @ L339

  • 方法名:getSectionRenderDispatcher
  • 源码定位:L339
  • 返回类型:SectionRenderDispatcher
  • 修饰符:public

参数:

说明:

TODO

public double getTotalSections() @ L343

  • 方法名:getTotalSections
  • 源码定位:L343
  • 返回类型:double
  • 修饰符:public

参数:

说明:

TODO

public double getLastViewDistance() @ L347

  • 方法名:getLastViewDistance
  • 源码定位:L347
  • 返回类型:double
  • 修饰符:public

参数:

说明:

TODO

public int countRenderedSections() @ L351

  • 方法名:countRenderedSections
  • 源码定位:L351
  • 返回类型:int
  • 修饰符:public

参数:

说明:

TODO

public void resetSampler() @ L363

  • 方法名:resetSampler
  • 源码定位:L363
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public String getEntityStatistics() @ L371

  • 方法名:getEntityStatistics
  • 源码定位:L371
  • 返回类型:String
  • 修饰符:public

参数:

说明:

TODO

private void cullTerrain(Camera camera, Frustum frustum, boolean spectator) @ L382

  • 方法名:cullTerrain
  • 源码定位:L382
  • 返回类型:void
  • 修饰符:private

参数:

  • camera: Camera
  • frustum: Frustum
  • spectator: boolean

说明:

TODO

public static Frustum offsetFrustum(Frustum frustum) @ L439

  • 方法名:offsetFrustum
  • 源码定位:L439
  • 返回类型:Frustum
  • 修饰符:public static

参数:

  • frustum: Frustum

说明:

TODO

private void applyFrustum(Frustum frustum) @ L443

  • 方法名:applyFrustum
  • 源码定位:L443
  • 返回类型:void
  • 修饰符:private

参数:

  • frustum: Frustum

说明:

TODO

public void addRecentlyCompiledSection(SectionRenderDispatcher.RenderSection section) @ L452

  • 方法名:addRecentlyCompiledSection
  • 源码定位:L452
  • 返回类型:void
  • 修饰符:public

参数:

  • section: SectionRenderDispatcher.RenderSection

说明:

TODO

public void update(Camera camera) @ L456

  • 方法名:update
  • 源码定位:L456
  • 返回类型:void
  • 修饰符:public

参数:

  • camera: Camera

说明:

TODO

public void renderLevel(GraphicsResourceAllocator resourceAllocator, DeltaTracker deltaTracker, boolean renderOutline, CameraRenderState cameraState, Matrix4fc modelViewMatrix, GpuBufferSlice terrainFog, Vector4f fogColor, boolean shouldRenderSky, ChunkSectionsToRender chunkSectionsToRender) @ L465

  • 方法名:renderLevel
  • 源码定位:L465
  • 返回类型:void
  • 修饰符:public

参数:

  • resourceAllocator: GraphicsResourceAllocator
  • deltaTracker: DeltaTracker
  • renderOutline: boolean
  • cameraState: CameraRenderState
  • modelViewMatrix: Matrix4fc
  • terrainFog: GpuBufferSlice
  • fogColor: Vector4f
  • shouldRenderSky: boolean
  • chunkSectionsToRender: ChunkSectionsToRender

说明:

TODO

public void extractLevel(DeltaTracker deltaTracker, Camera camera, float deltaPartialTick) @ L569

  • 方法名:extractLevel
  • 源码定位:L569
  • 返回类型:void
  • 修饰符:public

参数:

  • deltaTracker: DeltaTracker
  • camera: Camera
  • deltaPartialTick: float

说明:

TODO

private void addMainPass(FrameGraphBuilder frame, Frustum frustum, Matrix4fc modelViewMatrix, GpuBufferSlice terrainFog, boolean renderOutline, LevelRenderState levelRenderState, DeltaTracker deltaTracker, ProfilerFiller profiler, ChunkSectionsToRender chunkSectionsToRender) @ L617

  • 方法名:addMainPass
  • 源码定位:L617
  • 返回类型:void
  • 修饰符:private

参数:

  • frame: FrameGraphBuilder
  • frustum: Frustum
  • modelViewMatrix: Matrix4fc
  • terrainFog: GpuBufferSlice
  • renderOutline: boolean
  • levelRenderState: LevelRenderState
  • deltaTracker: DeltaTracker
  • profiler: ProfilerFiller
  • chunkSectionsToRender: ChunkSectionsToRender

说明:

TODO

private void addCloudsPass(FrameGraphBuilder frame, CloudStatus cloudStatus, Vec3 cameraPosition, long gameTime, float partialTicks, int cloudColor, float cloudHeight, int cloudRange) @ L738

  • 方法名:addCloudsPass
  • 源码定位:L738
  • 返回类型:void
  • 修饰符:private

参数:

  • frame: FrameGraphBuilder
  • cloudStatus: CloudStatus
  • cameraPosition: Vec3
  • gameTime: long
  • partialTicks: float
  • cloudColor: int
  • cloudHeight: float
  • cloudRange: int

说明:

TODO

private void addWeatherPass(FrameGraphBuilder frame, GpuBufferSlice fog) @ L758

  • 方法名:addWeatherPass
  • 源码定位:L758
  • 返回类型:void
  • 修饰符:private

参数:

  • frame: FrameGraphBuilder
  • fog: GpuBufferSlice

说明:

TODO

private void addLateDebugPass(FrameGraphBuilder frame, CameraRenderState camera, GpuBufferSlice fog, Matrix4fc modelViewMatrix) @ L778

  • 方法名:addLateDebugPass
  • 源码定位:L778
  • 返回类型:void
  • 修饰符:private

参数:

  • frame: FrameGraphBuilder
  • camera: CameraRenderState
  • fog: GpuBufferSlice
  • modelViewMatrix: Matrix4fc

说明:

TODO

private void extractVisibleEntities(Camera camera, Frustum frustum, DeltaTracker deltaTracker, LevelRenderState output) @ L805

  • 方法名:extractVisibleEntities
  • 源码定位:L805
  • 返回类型:void
  • 修饰符:private

参数:

  • camera: Camera
  • frustum: Frustum
  • deltaTracker: DeltaTracker
  • output: LevelRenderState

说明:

TODO

private void submitEntities(PoseStack poseStack, LevelRenderState levelRenderState, SubmitNodeCollector output) @ L845

  • 方法名:submitEntities
  • 源码定位:L845
  • 返回类型:void
  • 修饰符:private

参数:

  • poseStack: PoseStack
  • levelRenderState: LevelRenderState
  • output: SubmitNodeCollector

说明:

TODO

private void extractVisibleBlockEntities(Camera camera, float deltaPartialTick, LevelRenderState levelRenderState) @ L860

  • 方法名:extractVisibleBlockEntities
  • 源码定位:L860
  • 返回类型:void
  • 修饰符:private

参数:

  • camera: Camera
  • deltaPartialTick: float
  • levelRenderState: LevelRenderState

说明:

TODO

private void submitBlockEntities(PoseStack poseStack, LevelRenderState levelRenderState, SubmitNodeStorage submitNodeStorage) @ L906

  • 方法名:submitBlockEntities
  • 源码定位:L906
  • 返回类型:void
  • 修饰符:private

参数:

  • poseStack: PoseStack
  • levelRenderState: LevelRenderState
  • submitNodeStorage: SubmitNodeStorage

说明:

TODO

private void extractBlockDestroyAnimation(Camera camera, LevelRenderState levelRenderState) @ L921

  • 方法名:extractBlockDestroyAnimation
  • 源码定位:L921
  • 返回类型:void
  • 修饰符:private

参数:

  • camera: Camera
  • levelRenderState: LevelRenderState

说明:

TODO

private void submitBlockDestroyAnimation(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, LevelRenderState levelRenderState) @ L940

  • 方法名:submitBlockDestroyAnimation
  • 源码定位:L940
  • 返回类型:void
  • 修饰符:private

参数:

  • poseStack: PoseStack
  • submitNodeCollector: SubmitNodeCollector
  • levelRenderState: LevelRenderState

说明:

TODO

private void extractBlockOutline(Camera camera, LevelRenderState levelRenderState) @ L958

  • 方法名:extractBlockOutline
  • 源码定位:L958
  • 返回类型:void
  • 修饰符:private

参数:

  • camera: Camera
  • levelRenderState: LevelRenderState

说明:

TODO

private void renderBlockOutline(MultiBufferSource.BufferSource bufferSource, PoseStack poseStack, boolean onlyTranslucentBlocks, LevelRenderState levelRenderState) @ L985

  • 方法名:renderBlockOutline
  • 源码定位:L985
  • 返回类型:void
  • 修饰符:private

参数:

  • bufferSource: MultiBufferSource.BufferSource
  • poseStack: PoseStack
  • onlyTranslucentBlocks: boolean
  • levelRenderState: LevelRenderState

说明:

TODO

private void checkPoseStack(PoseStack poseStack) @ L1014

  • 方法名:checkPoseStack
  • 源码定位:L1014
  • 返回类型:void
  • 修饰符:private

参数:

  • poseStack: PoseStack

说明:

TODO

private EntityRenderState extractEntity(Entity entity, float partialTickTime) @ L1020

  • 方法名:extractEntity
  • 源码定位:L1020
  • 返回类型:EntityRenderState
  • 修饰符:private

参数:

  • entity: Entity
  • partialTickTime: float

说明:

TODO

private void scheduleTranslucentSectionResort(Vec3 cameraPos) @ L1024

  • 方法名:scheduleTranslucentSectionResort
  • 源码定位:L1024
  • 返回类型:void
  • 修饰符:private

参数:

  • cameraPos: Vec3

说明:

TODO

private void scheduleResort(SectionRenderDispatcher.RenderSection section, TranslucencyPointOfView pointOfView, Vec3 cameraPos, boolean blockPosChanged, boolean isNearby) @ L1046

  • 方法名:scheduleResort
  • 源码定位:L1046
  • 返回类型:void
  • 修饰符:private

参数:

  • section: SectionRenderDispatcher.RenderSection
  • pointOfView: TranslucencyPointOfView
  • cameraPos: Vec3
  • blockPosChanged: boolean
  • isNearby: boolean

说明:

TODO

public ChunkSectionsToRender prepareChunkRenders(Matrix4fc modelViewMatrix) @ L1057

  • 方法名:prepareChunkRenders
  • 源码定位:L1057
  • 返回类型:ChunkSectionsToRender
  • 修饰符:public

参数:

  • modelViewMatrix: Matrix4fc

说明:

TODO

public void endFrame() @ L1160

  • 方法名:endFrame
  • 源码定位:L1160
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public void tick(Camera camera) @ L1164

  • 方法名:tick
  • 源码定位:L1164
  • 返回类型:void
  • 修饰符:public

参数:

  • camera: Camera

说明:

TODO

private void removeBlockBreakingProgress() @ L1174

  • 方法名:removeBlockBreakingProgress
  • 源码定位:L1174
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

private void removeProgress(BlockDestructionProgress block) @ L1189

  • 方法名:removeProgress
  • 源码定位:L1189
  • 返回类型:void
  • 修饰符:private

参数:

  • block: BlockDestructionProgress

说明:

TODO

private void addSkyPass(FrameGraphBuilder frame, CameraRenderState cameraState, GpuBufferSlice skyFog) @ L1198

  • 方法名:addSkyPass
  • 源码定位:L1198
  • 返回类型:void
  • 修饰符:private

参数:

  • frame: FrameGraphBuilder
  • cameraState: CameraRenderState
  • skyFog: GpuBufferSlice

说明:

TODO

private void compileSections(Camera camera) @ L1234

  • 方法名:compileSections
  • 源码定位:L1234
  • 返回类型:void
  • 修饰符:private

参数:

  • camera: Camera

说明:

TODO

private void renderHitOutline(PoseStack poseStack, VertexConsumer builder, double camX, double camY, double camZ, BlockOutlineRenderState state, int color, float width) @ L1284

  • 方法名:renderHitOutline
  • 源码定位:L1284
  • 返回类型:void
  • 修饰符:private

参数:

  • poseStack: PoseStack
  • builder: VertexConsumer
  • camX: double
  • camY: double
  • camZ: double
  • state: BlockOutlineRenderState
  • color: int
  • width: float

说明:

TODO

public void blockChanged(BlockGetter level, BlockPos pos, BlockState old, BlockState current, int updateFlags) @ L1335

  • 方法名:blockChanged
  • 源码定位:L1335
  • 返回类型:void
  • 修饰符:public

参数:

  • level: BlockGetter
  • pos: BlockPos
  • old: BlockState
  • current: BlockState
  • updateFlags: int

说明:

TODO

private void setBlockDirty(BlockPos pos, boolean playerChanged) @ L1339

  • 方法名:setBlockDirty
  • 源码定位:L1339
  • 返回类型:void
  • 修饰符:private

参数:

  • pos: BlockPos
  • playerChanged: boolean

说明:

TODO

public void setBlocksDirty(int x0, int y0, int z0, int x1, int y1, int z1) @ L1349

  • 方法名:setBlocksDirty
  • 源码定位:L1349
  • 返回类型:void
  • 修饰符:public

参数:

  • x0: int
  • y0: int
  • z0: int
  • x1: int
  • y1: int
  • z1: int

说明:

TODO

public void setBlockDirty(BlockPos pos, BlockState oldState, BlockState newState) @ L1359

  • 方法名:setBlockDirty
  • 源码定位:L1359
  • 返回类型:void
  • 修饰符:public

参数:

  • pos: BlockPos
  • oldState: BlockState
  • newState: BlockState

说明:

TODO

public void setSectionDirtyWithNeighbors(int sectionX, int sectionY, int sectionZ) @ L1365

  • 方法名:setSectionDirtyWithNeighbors
  • 源码定位:L1365
  • 返回类型:void
  • 修饰符:public

参数:

  • sectionX: int
  • sectionY: int
  • sectionZ: int

说明:

TODO

public void setSectionRangeDirty(int minSectionX, int minSectionY, int minSectionZ, int maxSectionX, int maxSectionY, int maxSectionZ) @ L1369

  • 方法名:setSectionRangeDirty
  • 源码定位:L1369
  • 返回类型:void
  • 修饰符:public

参数:

  • minSectionX: int
  • minSectionY: int
  • minSectionZ: int
  • maxSectionX: int
  • maxSectionY: int
  • maxSectionZ: int

说明:

TODO

public void setSectionDirty(int sectionX, int sectionY, int sectionZ) @ L1379

  • 方法名:setSectionDirty
  • 源码定位:L1379
  • 返回类型:void
  • 修饰符:public

参数:

  • sectionX: int
  • sectionY: int
  • sectionZ: int

说明:

TODO

private void setSectionDirty(int sectionX, int sectionY, int sectionZ, boolean playerChanged) @ L1383

  • 方法名:setSectionDirty
  • 源码定位:L1383
  • 返回类型:void
  • 修饰符:private

参数:

  • sectionX: int
  • sectionY: int
  • sectionZ: int
  • playerChanged: boolean

说明:

TODO

public void onSectionBecomingNonEmpty(long sectionNode) @ L1387

  • 方法名:onSectionBecomingNonEmpty
  • 源码定位:L1387
  • 返回类型:void
  • 修饰符:public

参数:

  • sectionNode: long

说明:

TODO

public void destroyBlockProgress(int id, BlockPos pos, int progress) @ L1395

  • 方法名:destroyBlockProgress
  • 源码定位:L1395
  • 返回类型:void
  • 修饰符:public

参数:

  • id: int
  • pos: BlockPos
  • progress: int

说明:

TODO

public boolean hasRenderedAllSections() @ L1418

  • 方法名:hasRenderedAllSections
  • 源码定位:L1418
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

public void onChunkReadyToRender(ChunkPos pos) @ L1422

  • 方法名:onChunkReadyToRender
  • 源码定位:L1422
  • 返回类型:void
  • 修饰符:public

参数:

  • pos: ChunkPos

说明:

TODO

public void needsUpdate() @ L1426

  • 方法名:needsUpdate
  • 源码定位:L1426
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public static int getLightCoords(BlockAndLightGetter level, BlockPos pos) @ L1431

  • 方法名:getLightCoords
  • 源码定位:L1431
  • 返回类型:int
  • 修饰符:public static

参数:

  • level: BlockAndLightGetter
  • pos: BlockPos

说明:

TODO

public static int getLightCoords(LevelRenderer.BrightnessGetter brightnessGetter, BlockAndLightGetter level, BlockState state, BlockPos pos) @ L1435

  • 方法名:getLightCoords
  • 源码定位:L1435
  • 返回类型:int
  • 修饰符:public static

参数:

  • brightnessGetter: LevelRenderer.BrightnessGetter
  • level: BlockAndLightGetter
  • state: BlockState
  • pos: BlockPos

说明:

TODO

public boolean isSectionCompiledAndVisible(BlockPos blockPos) @ L1446

  • 方法名:isSectionCompiledAndVisible
  • 源码定位:L1446
  • 返回类型:boolean
  • 修饰符:public

参数:

  • blockPos: BlockPos

说明:

TODO

public RenderTarget entityOutlineTarget() @ L1453

  • 方法名:entityOutlineTarget
  • 源码定位:L1453
  • 返回类型:RenderTarget
  • 修饰符:public

参数:

说明:

TODO

public RenderTarget getTranslucentTarget() @ L1457

  • 方法名:getTranslucentTarget
  • 源码定位:L1457
  • 返回类型:RenderTarget
  • 修饰符:public

参数:

说明:

TODO

public RenderTarget getItemEntityTarget() @ L1461

  • 方法名:getItemEntityTarget
  • 源码定位:L1461
  • 返回类型:RenderTarget
  • 修饰符:public

参数:

说明:

TODO

public RenderTarget getParticlesTarget() @ L1465

  • 方法名:getParticlesTarget
  • 源码定位:L1465
  • 返回类型:RenderTarget
  • 修饰符:public

参数:

说明:

TODO

public RenderTarget getWeatherTarget() @ L1469

  • 方法名:getWeatherTarget
  • 源码定位:L1469
  • 返回类型:RenderTarget
  • 修饰符:public

参数:

说明:

TODO

public RenderTarget getCloudsTarget() @ L1473

  • 方法名:getCloudsTarget
  • 源码定位:L1473
  • 返回类型:RenderTarget
  • 修饰符:public

参数:

说明:

TODO

public ObjectArrayList<SectionRenderDispatcher.RenderSection> getVisibleSections() @ L1477

  • 方法名:getVisibleSections
  • 源码定位:L1477
  • 返回类型:ObjectArrayList<SectionRenderDispatcher.RenderSection>
  • 修饰符:public

参数:

说明:

TODO

public SectionOcclusionGraph getSectionOcclusionGraph() @ L1482

  • 方法名:getSectionOcclusionGraph
  • 源码定位:L1482
  • 返回类型:SectionOcclusionGraph
  • 修饰符:public

参数:

说明:

TODO

public CloudRenderer getCloudRenderer() @ L1487

  • 方法名:getCloudRenderer
  • 源码定位:L1487
  • 返回类型:CloudRenderer
  • 修饰符:public

参数:

说明:

TODO

public Gizmos.TemporaryCollection collectPerFrameGizmos() @ L1491

  • 方法名:collectPerFrameGizmos
  • 源码定位:L1491
  • 返回类型:Gizmos.TemporaryCollection
  • 修饰符:public

参数:

说明:

TODO

private void finalizeGizmoCollection() @ L1495

  • 方法名:finalizeGizmoCollection
  • 源码定位:L1495
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
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();
    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<SectionRenderDispatcher.RenderSection> visibleSections = new ObjectArrayList<>(10000);
    private final ObjectArrayList<SectionRenderDispatcher.RenderSection> nearbyVisibleSections = new ObjectArrayList<>(50);
    private @Nullable ViewArea viewArea;
    private int ticks;
    private final Int2ObjectMap<BlockDestructionProgress> destroyingBlocks = new Int2ObjectOpenHashMap<>();
    private final Long2ObjectMap<SortedSet<BlockDestructionProgress>> 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 boolean lastSmartCull = true;
    private @Nullable SectionRenderDispatcher sectionRenderDispatcher;
    private int lastViewDistance = -1;
    private @Nullable BlockPos lastTranslucentSortBlockPos;
    private int translucencyResortIterationIndex;
    private final OptionsRenderState optionsRenderState;
    private final LevelRenderState levelRenderState;
    private final SubmitNodeStorage submitNodeStorage;
    private final FeatureRenderDispatcher featureRenderDispatcher;
    private @Nullable GpuSampler chunkLayerSampler;
    private final SimpleGizmoCollector collectedGizmos = new SimpleGizmoCollector();
    private LevelRenderer.FinalizedGizmos finalizedGizmos = new LevelRenderer.FinalizedGizmos(new DrawableGizmoPrimitives(), new DrawableGizmoPrimitives());
 
    public LevelRenderer(
        Minecraft minecraft,
        EntityRenderDispatcher entityRenderDispatcher,
        BlockEntityRenderDispatcher blockEntityRenderDispatcher,
        RenderBuffers renderBuffers,
        GameRenderState gameRenderState,
        FeatureRenderDispatcher featureRenderDispatcher
    ) {
        this.minecraft = minecraft;
        this.entityRenderDispatcher = entityRenderDispatcher;
        this.blockEntityRenderDispatcher = blockEntityRenderDispatcher;
        this.renderBuffers = renderBuffers;
        this.submitNodeStorage = featureRenderDispatcher.getSubmitNodeStorage();
        this.optionsRenderState = gameRenderState.optionsRenderState;
        this.levelRenderState = gameRenderState.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();
        }
 
        WindowRenderState windowState = this.minecraft.gameRenderer.getGameRenderState().windowRenderState;
        this.entityOutlineTarget = new TextureTarget("Entity Outline", windowState.width, windowState.height, true);
    }
 
    private @Nullable PostChain getTransparencyChain() {
        return !Minecraft.useShaderTransparency()
            ? null
            : this.minecraft.getShaderManager().getPostChain(TRANSPARENCY_POST_CHAIN_ID, LevelTargetBundle.SORTING_TARGETS);
    }
 
    public void doEntityOutline() {
        if (this.shouldShowEntityOutlines()) {
            this.entityOutlineTarget.blitAndBlendToTexture(this.minecraft.getMainRenderTarget().getColorTextureView());
        }
    }
 
    protected boolean shouldShowEntityOutlines() {
        return !this.levelRenderState.cameraRenderState.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) {
            this.level.clearTintCaches();
            Options options = this.minecraft.options;
            boolean ambientOcclusion = options.ambientOcclusion().get();
            boolean cutoutLeaves = options.cutoutLeaves().get();
            ModelManager modelManager = this.minecraft.getModelManager();
            SectionCompiler sectionCompiler = new SectionCompiler(
                ambientOcclusion,
                cutoutLeaves,
                modelManager.getBlockStateModelSet(),
                modelManager.getFluidStateModelSet(),
                this.minecraft.getBlockColors(),
                this.minecraft.getBlockEntityRenderDispatcher()
            );
            if (this.sectionRenderDispatcher == null) {
                this.sectionRenderDispatcher = new SectionRenderDispatcher(this.level, this, Util.backgroundExecutor(), this.renderBuffers, sectionCompiler);
            } else {
                this.sectionRenderDispatcher.setLevel(this.level, sectionCompiler);
            }
 
            this.cloudRenderer.markForRebuild();
            LeavesBlock.setCutoutLeaves(cutoutLeaves);
            this.lastViewDistance = options.getEffectiveRenderDistance();
            if (this.viewArea != null) {
                this.viewArea.releaseAllBuffers();
            }
 
            this.sectionRenderDispatcher.clearCompileQueue();
            this.viewArea = new ViewArea(this.sectionRenderDispatcher, this.level, 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;
        } else {
            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 : 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()) {
                rendered++;
            }
        }
 
        return rendered;
    }
 
    public void resetSampler() {
        if (this.chunkLayerSampler != null) {
            this.chunkLayerSampler.close();
        }
 
        this.chunkLayerSampler = null;
    }
 
    public @Nullable String getEntityStatistics() {
        return this.level == null
            ? null
            : "E: "
                + this.levelRenderState.lastEntityRenderStateCount
                + "/"
                + 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 (camera.getCapturedFrustum() == null) {
            boolean smartCull = this.minecraft.smartCull;
            if (spectator && this.level.getBlockState(camera.blockPosition()).isSolidRender()) {
                smartCull = false;
            }
 
            if (smartCull != this.lastSmartCull) {
                this.sectionOcclusionGraph.invalidate();
            }
 
            this.lastSmartCull = smartCull;
            profiler.push("updateSOG");
            this.sectionOcclusionGraph.update(smartCull, camera, frustum, 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(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());
        } else {
            this.clearVisibleSections();
            this.sectionOcclusionGraph.addSectionsInFrustum(frustum, this.visibleSections, this.nearbyVisibleSections);
        }
    }
 
    public void addRecentlyCompiledSection(SectionRenderDispatcher.RenderSection section) {
        this.sectionOcclusionGraph.schedulePropagationFrom(section);
    }
 
    public void update(Camera camera) {
        ProfilerFiller profiler = Profiler.get();
        profiler.push("cullTerrain");
        this.cullTerrain(camera, camera.getCullFrustum(), this.minecraft.player.isSpectator());
        profiler.popPush("compileSections");
        this.compileSections(camera);
        profiler.pop();
    }
 
    public void renderLevel(
        GraphicsResourceAllocator resourceAllocator,
        DeltaTracker deltaTracker,
        boolean renderOutline,
        CameraRenderState cameraState,
        Matrix4fc modelViewMatrix,
        GpuBufferSlice terrainFog,
        Vector4f fogColor,
        boolean shouldRenderSky,
        ChunkSectionsToRender chunkSectionsToRender
    ) {
        float deltaPartialTick = deltaTracker.getGameTimeDeltaPartialTick(false);
        this.levelRenderState.gameTime = this.level.getGameTime();
        final ProfilerFiller profiler = Profiler.get();
        Frustum cullFrustum = cameraState.cullFrustum;
        profiler.push("setupFrameGraph");
        Matrix4fStack modelViewStack = RenderSystem.getModelViewStack();
        modelViewStack.pushMatrix();
        modelViewStack.mul(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, cameraState, terrainFog);
        }
 
        this.addMainPass(frame, cullFrustum, modelViewMatrix, terrainFog, renderOutline, this.levelRenderState, deltaTracker, profiler, chunkSectionsToRender);
        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);
        }
 
        CloudStatus cloudStatus = this.optionsRenderState.cloudStatus;
        if (cloudStatus != CloudStatus.OFF && ARGB.alpha(this.levelRenderState.cloudColor) > 0) {
            this.addCloudsPass(
                frame,
                cloudStatus,
                this.levelRenderState.cameraRenderState.pos,
                this.levelRenderState.gameTime,
                deltaPartialTick,
                this.levelRenderState.cloudColor,
                this.levelRenderState.cloudHeight,
                this.optionsRenderState.cloudRange
            );
        }
 
        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() {
            {
                Objects.requireNonNull(LevelRenderer.this);
            }
 
            @Override
            public void beforeExecutePass(String name) {
                profiler.push(name);
            }
 
            @Override
            public void afterExecutePass(String name) {
                profiler.pop();
            }
        });
        profiler.pop();
        this.targets.clear();
        modelViewStack.popMatrix();
        this.levelRenderState.reset();
    }
 
    public void extractLevel(DeltaTracker deltaTracker, Camera camera, float deltaPartialTick) {
        ProfilerFiller profiler = Profiler.get();
        profiler.push("level");
        Vec3 cameraPos = camera.position();
        Frustum cullFrustum = camera.getCullFrustum();
        profiler.push("prepareDispatchers");
        this.blockEntityRenderDispatcher.prepare(cameraPos);
        this.entityRenderDispatcher.prepare(camera, this.minecraft.crosshairPickEntity);
        profiler.popPush("prepareChunkDraws");
        Matrix4f modelViewMatrix = new Matrix4f();
        camera.getViewRotationMatrix(modelViewMatrix);
        this.levelRenderState.chunkSectionsToRender = this.prepareChunkRenders(modelViewMatrix);
        profiler.popPush("entities");
        this.extractVisibleEntities(camera, cullFrustum, 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.popPush("particles");
        this.minecraft.particleEngine.extract(this.levelRenderState.particlesRenderState, new Frustum(cullFrustum).offset(-3.0F), camera, deltaPartialTick);
        profiler.popPush("cloud");
        this.levelRenderState.cloudColor = camera.attributeProbe().getValue(EnvironmentAttributes.CLOUD_COLOR, deltaPartialTick);
        if (ARGB.alpha(this.levelRenderState.cloudColor) > 0) {
            this.levelRenderState.cloudHeight = camera.attributeProbe().getValue(EnvironmentAttributes.CLOUD_HEIGHT, deltaPartialTick);
        }
 
        profiler.popPush("debug");
        this.debugRenderer.emitGizmos(cullFrustum, cameraPos.x, cameraPos.y, cameraPos.z, deltaTracker.getGameTimeDeltaPartialTick(false));
        this.gameTestBlockHighlightRenderer.emitGizmos();
        profiler.pop();
        profiler.pop();
    }
 
    private void addMainPass(
        FrameGraphBuilder frame,
        Frustum frustum,
        Matrix4fc modelViewMatrix,
        GpuBufferSlice terrainFog,
        boolean renderOutline,
        LevelRenderState levelRenderState,
        DeltaTracker deltaTracker,
        ProfilerFiller profiler,
        ChunkSectionsToRender chunkSectionsToRender
    ) {
        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 (this.targets.particles != null) {
            this.targets.particles = pass.readsAndWrites(this.targets.particles);
        }
 
        if (levelRenderState.haveGlowingEntities && this.targets.entityOutline != null) {
            this.targets.entityOutline = pass.readsAndWrites(this.targets.entityOutline);
        }
 
        ResourceHandle<RenderTarget> mainTarget = this.targets.main;
        ResourceHandle<RenderTarget> translucentTarget = this.targets.translucent;
        ResourceHandle<RenderTarget> itemEntityTarget = this.targets.itemEntity;
        ResourceHandle<RenderTarget> entityOutlineTarget = this.targets.entityOutline;
        ResourceHandle<RenderTarget> particleTarget = this.targets.particles;
        pass.executes(
            () -> {
                RenderSystem.setShaderFog(terrainFog);
                Vec3 cameraPos = levelRenderState.cameraRenderState.pos;
                double camX = cameraPos.x();
                double camY = cameraPos.y();
                double camZ = cameraPos.z();
                profiler.push("solidTerrain");
                if (this.chunkLayerSampler == null) {
                    int maxAnisotropy = this.optionsRenderState.textureFiltering == TextureFilteringMethod.ANISOTROPIC
                        ? this.optionsRenderState.maxAnisotropyValue
                        : 1;
                    this.chunkLayerSampler = RenderSystem.getDevice()
                        .createSampler(
                            AddressMode.CLAMP_TO_EDGE, AddressMode.CLAMP_TO_EDGE, FilterMode.LINEAR, FilterMode.LINEAR, maxAnisotropy, OptionalDouble.empty()
                        );
                }
 
                chunkSectionsToRender.renderGroup(ChunkSectionLayerGroup.OPAQUE, this.chunkLayerSampler);
                this.minecraft.gameRenderer.getLighting().setupFor(Lighting.Entry.LEVEL);
                if (this.shouldShowEntityOutlines() && entityOutlineTarget != null) {
                    RenderTarget outlineTarget = 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("submitFeatures");
                this.submitEntities(poseStack, levelRenderState, this.submitNodeStorage);
                this.submitBlockEntities(poseStack, levelRenderState, this.submitNodeStorage);
                levelRenderState.particlesRenderState.submit(this.submitNodeStorage, levelRenderState.cameraRenderState);
                this.submitBlockDestroyAnimation(poseStack, this.submitNodeStorage, levelRenderState);
                profiler.popPush("renderSolidFeatures");
                this.featureRenderDispatcher.renderSolidFeatures();
                bufferSource.endBatch();
                profiler.pop();
                this.checkPoseStack(poseStack);
                if (translucentTarget != null) {
                    translucentTarget.get().copyDepthFrom(mainTarget.get());
                }
 
                if (itemEntityTarget != null) {
                    itemEntityTarget.get().copyDepthFrom(mainTarget.get());
                }
 
                if (particleTarget != null) {
                    particleTarget.get().copyDepthFrom(mainTarget.get());
                }
 
                profiler.push("renderTranslucentFeatures");
                this.featureRenderDispatcher.renderTranslucentFeatures();
                bufferSource.endBatch();
                crumblingBufferSource.endBatch();
                profiler.pop();
                this.renderBuffers.outlineBufferSource().endOutlineBatch();
                if (renderOutline) {
                    this.renderBlockOutline(bufferSource, poseStack, false, levelRenderState);
                    bufferSource.endBatch();
                }
 
                this.finalizeGizmoCollection();
                this.finalizedGizmos.standardPrimitives().render(poseStack, bufferSource, levelRenderState.cameraRenderState, modelViewMatrix);
                bufferSource.endBatch();
                this.checkPoseStack(poseStack);
                profiler.push("translucentTerrain");
                chunkSectionsToRender.renderGroup(ChunkSectionLayerGroup.TRANSLUCENT, this.chunkLayerSampler);
                if (renderOutline) {
                    this.renderBlockOutline(bufferSource, poseStack, true, levelRenderState);
                }
 
                bufferSource.endBatch();
                profiler.pop();
                this.featureRenderDispatcher.renderTranslucentParticles();
                bufferSource.endBatch();
                this.featureRenderDispatcher.clearSubmitNodes();
                levelRenderState.particlesRenderState.reset();
            }
        );
    }
 
    private void addCloudsPass(
        FrameGraphBuilder frame,
        CloudStatus cloudStatus,
        Vec3 cameraPosition,
        long gameTime,
        float partialTicks,
        int cloudColor,
        float cloudHeight,
        int cloudRange
    ) {
        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, cloudStatus, cloudHeight, cloudRange, cameraPosition, gameTime, partialTicks));
    }
 
    private void addWeatherPass(FrameGraphBuilder frame, GpuBufferSlice fog) {
        int renderDistance = this.optionsRenderState.renderDistance * 16;
        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);
                CameraRenderState cameraState = this.levelRenderState.cameraRenderState;
                this.weatherEffectRenderer.render(cameraState.pos, this.levelRenderState.weatherRenderState);
                this.worldBorderRenderer
                    .render(this.levelRenderState.worldBorderRenderState, cameraState.pos, renderDistance, this.levelRenderState.cameraRenderState.depthFar);
            }
        );
    }
 
    private void addLateDebugPass(FrameGraphBuilder frame, CameraRenderState camera, GpuBufferSlice fog, Matrix4fc 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<RenderTarget> mainTarget = this.targets.main;
        pass.executes(() -> {
            RenderSystem.setShaderFog(fog);
            PoseStack poseStack = new PoseStack();
            MultiBufferSource.BufferSource bufferSource = this.renderBuffers.bufferSource();
            RenderSystem.outputColorTextureOverride = mainTarget.get().getColorTextureView();
            RenderSystem.outputDepthTextureOverride = mainTarget.get().getDepthTextureView();
            if (!this.finalizedGizmos.alwaysOnTopPrimitives().isEmpty()) {
                RenderTarget mainRenderTarget = Minecraft.getInstance().getMainRenderTarget();
                RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(mainRenderTarget.getDepthTexture(), 1.0);
                this.finalizedGizmos.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(this.minecraft.options.getEffectiveRenderDistance() / 8.0, 1.0, 2.5) * this.minecraft.options.entityDistanceScaling().get()
        );
 
        for (Entity entity : this.level.entitiesForRendering()) {
            if (this.entityRenderDispatcher.shouldRender(entity, frustum, camX, camY, camZ) || entity.hasIndirectPassenger(this.minecraft.player)) {
                BlockPos blockPos = entity.blockPosition();
                if ((this.level.isOutsideBuildHeight(blockPos.getY()) || this.isSectionCompiledAndVisible(blockPos))
                    && (
                        entity != camera.entity()
                            || camera.isDetached()
                            || camera.entity() instanceof LivingEntity && ((LivingEntity)camera.entity()).isSleeping()
                    )
                    && (!(entity instanceof LocalPlayer) || camera.entity() == entity)) {
                    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) {
                        output.haveGlowingEntities = true;
                    }
                }
            }
        }
 
        output.lastEntityRenderStateCount = output.entityRenderStates.size();
    }
 
    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<BlockEntity> renderableBlockEntities = section.getSectionMesh().getRenderableBlockEntities();
            if (!renderableBlockEntities.isEmpty() && !(section.getVisibility(Util.getMillis()) < 0.3F)) {
                for (BlockEntity blockEntity : renderableBlockEntities) {
                    BlockPos blockPos = blockEntity.getBlockPos();
                    SortedSet<BlockDestructionProgress> progresses = this.destructionProgress.get(blockPos.asLong());
                    ModelFeatureRenderer.CrumblingOverlay breakProgress;
                    if (progresses != null && !progresses.isEmpty()) {
                        poseStack.pushPose();
                        poseStack.translate(blockPos.getX() - camX, blockPos.getY() - camY, blockPos.getZ() - camZ);
                        breakProgress = new ModelFeatureRenderer.CrumblingOverlay(progresses.last().getProgress(), poseStack.last());
                        poseStack.popPose();
                    } else {
                        breakProgress = null;
                    }
 
                    BlockEntityRenderState state = this.blockEntityRenderDispatcher.tryExtractRenderState(blockEntity, deltaPartialTick, breakProgress);
                    if (state != null) {
                        levelRenderState.blockEntityRenderStates.add(state);
                    }
                }
            }
        }
 
        Iterator<BlockEntity> iterator = this.level.getGloballyRenderedBlockEntities().iterator();
 
        while (iterator.hasNext()) {
            BlockEntity blockEntity = iterator.next();
            if (blockEntity.isRemoved()) {
                iterator.remove();
            } else {
                BlockEntityRenderState state = this.blockEntityRenderDispatcher.tryExtractRenderState(blockEntity, deltaPartialTick, null);
                if (state != null) {
                    levelRenderState.blockEntityRenderStates.add(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(blockPos.getX() - camX, blockPos.getY() - camY, 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 (Entry<SortedSet<BlockDestructionProgress>> entry : this.destructionProgress.long2ObjectEntrySet()) {
            BlockPos pos = BlockPos.of(entry.getLongKey());
            if (!(pos.distToCenterSqr(camX, camY, camZ) > 1024.0)) {
                SortedSet<BlockDestructionProgress> progresses = entry.getValue();
                if (progresses != null && !progresses.isEmpty()) {
                    int progress = progresses.last().getProgress();
                    levelRenderState.blockBreakingRenderStates.add(new BlockBreakingRenderState(pos, this.level.getBlockState(pos), progress));
                }
            }
        }
    }
 
    private void submitBlockDestroyAnimation(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, LevelRenderState levelRenderState) {
        Vec3 cameraPos = levelRenderState.cameraRenderState.pos;
        double camX = cameraPos.x();
        double camY = cameraPos.y();
        double camZ = cameraPos.z();
 
        for (BlockBreakingRenderState state : levelRenderState.blockBreakingRenderStates) {
            if (state.blockState().getRenderShape() == RenderShape.MODEL) {
                BlockPos pos = state.blockPos();
                poseStack.pushPose();
                poseStack.translate(pos.getX() - camX, pos.getY() - camY, pos.getZ() - camZ);
                BlockStateModel model = this.minecraft.getModelManager().getBlockStateModelSet().get(state.blockState());
                submitNodeCollector.submitBreakingBlockModel(poseStack, model, state.blockState().getSeed(pos), state.progress());
                poseStack.popPose();
            }
        }
    }
 
    private void extractBlockOutline(Camera camera, LevelRenderState levelRenderState) {
        levelRenderState.blockOutlineRenderState = null;
        if (this.minecraft.hitResult instanceof BlockHitResult blockHitResult) {
            if (blockHitResult.getType() != HitResult.Type.MISS) {
                BlockPos pos = blockHitResult.getBlockPos();
                BlockState state = this.level.getBlockState(pos);
                if (!state.isAir() && this.level.getWorldBorder().isWithinBounds(pos)) {
                    BlockStateModel blockStateModel = this.minecraft.getModelManager().getBlockStateModelSet().get(state);
                    boolean isBlockTranslucent = blockStateModel.hasMaterialFlag(1);
                    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
    ) {
        BlockOutlineRenderState state = levelRenderState.blockOutlineRenderState;
        if (state != null) {
            if (state.isTranslucent() == onlyTranslucentBlocks) {
                Vec3 cameraPos = levelRenderState.cameraRenderState.pos;
                if (state.highContrast()) {
                    VertexConsumer buffer = bufferSource.getBuffer(RenderTypes.secondaryBlockOutline());
                    this.renderHitOutline(poseStack, buffer, cameraPos.x, cameraPos.y, cameraPos.z, state, -16777216, 7.0F);
                }
 
                VertexConsumer 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.gameRenderer.getGameRenderState().windowRenderState.appropriateLineWidth
                );
                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()) {
            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.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(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
    ) {
        pointOfView.set(cameraPos, section.getSectionNode());
        boolean pointOfViewChanged = section.getSectionMesh().isDifferentPointOfView(pointOfView);
        boolean resortBecauseBlockPosChanged = blockPosChanged && (pointOfView.isAxisAligned() || isNearby);
        if ((resortBecauseBlockPosChanged || pointOfViewChanged) && !section.transparencyResortingScheduled() && section.hasTranslucentGeometry()) {
            section.resortTransparency(this.sectionRenderDispatcher);
        }
    }
 
    public ChunkSectionsToRender prepareChunkRenders(Matrix4fc modelViewMatrix) {
        ObjectListIterator<SectionRenderDispatcher.RenderSection> iterator = this.visibleSections.listIterator(0);
        EnumMap<ChunkSectionLayer, Int2ObjectOpenHashMap<List<RenderPass.Draw<GpuBufferSlice[]>>>> drawGroups = new EnumMap<>(ChunkSectionLayer.class);
        int largestIndexCount = 0;
 
        for (ChunkSectionLayer layer : ChunkSectionLayer.values()) {
            drawGroups.put(layer, new Int2ObjectOpenHashMap<>());
        }
 
        List<DynamicUniforms.ChunkSectionInfo> sectionInfos = new ArrayList<>();
        GpuTextureView blockAtlas = this.minecraft.getTextureManager().getTexture(TextureAtlas.LOCATION_BLOCKS).getTextureView();
        int textureAtlasWidth = blockAtlas.getWidth(0);
        int textureAtlasHeight = blockAtlas.getHeight(0);
        if (this.sectionRenderDispatcher != null) {
            this.sectionRenderDispatcher.lock();
 
            try {
                try (Zone ignored = Profiler.get().zone("Upload Global Buffers")) {
                    this.sectionRenderDispatcher.uploadGlobalGeomBuffersToGPU();
                }
 
                while (iterator.hasNext()) {
                    SectionRenderDispatcher.RenderSection section = iterator.next();
                    SectionMesh sectionMesh = section.getSectionMesh();
                    BlockPos renderOffset = section.getRenderOrigin();
                    long now = Util.getMillis();
                    int uboIndex = -1;
 
                    for (ChunkSectionLayer layer : ChunkSectionLayer.values()) {
                        SectionMesh.SectionDraw draw = sectionMesh.getSectionDraw(layer);
                        SectionRenderDispatcher.RenderSectionBufferSlice slice = this.sectionRenderDispatcher.getRenderSectionSlice(sectionMesh, layer);
                        if (slice != null && draw != null && (!draw.hasCustomIndexBuffer() || slice.indexBuffer() != null)) {
                            if (uboIndex == -1) {
                                uboIndex = sectionInfos.size();
                                sectionInfos.add(
                                    new DynamicUniforms.ChunkSectionInfo(
                                        new Matrix4f(modelViewMatrix),
                                        renderOffset.getX(),
                                        renderOffset.getY(),
                                        renderOffset.getZ(),
                                        section.getVisibility(now),
                                        textureAtlasWidth,
                                        textureAtlasHeight
                                    )
                                );
                            }
 
                            int combinedHash = 173;
                            VertexFormat vertexFormat = layer.pipeline().getVertexFormat();
                            GpuBuffer vertexBuffer = slice.vertexBuffer();
                            if (layer != ChunkSectionLayer.TRANSLUCENT) {
                                combinedHash = 31 * combinedHash + vertexBuffer.hashCode();
                            }
 
                            int firstIndex = 0;
                            GpuBuffer indexBuffer;
                            VertexFormat.IndexType indexType;
                            if (!draw.hasCustomIndexBuffer()) {
                                if (draw.indexCount() > largestIndexCount) {
                                    largestIndexCount = draw.indexCount();
                                }
 
                                indexBuffer = null;
                                indexType = null;
                            } else {
                                indexBuffer = slice.indexBuffer();
                                indexType = draw.indexType();
                                if (layer != ChunkSectionLayer.TRANSLUCENT) {
                                    combinedHash = 31 * combinedHash + indexBuffer.hashCode();
                                    combinedHash = 31 * combinedHash + indexType.hashCode();
                                }
 
                                firstIndex = (int)(slice.indexBufferOffset() / indexType.bytes);
                            }
 
                            int finalUboIndex = uboIndex;
                            int baseVertex = (int)(slice.vertexBufferOffset() / vertexFormat.getVertexSize());
                            List<RenderPass.Draw<GpuBufferSlice[]>> draws = drawGroups.get(layer).computeIfAbsent(combinedHash, var0 -> new ArrayList<>());
                            draws.add(
                                new RenderPass.Draw<>(
                                    0,
                                    vertexBuffer,
                                    indexBuffer,
                                    indexType,
                                    firstIndex,
                                    draw.indexCount(),
                                    baseVertex,
                                    (sectionUbos, uploader) -> uploader.upload("ChunkSection", sectionUbos[finalUboIndex])
                                )
                            );
                        }
                    }
                }
            } finally {
                this.sectionRenderDispatcher.unlock();
            }
        }
 
        GpuBufferSlice[] chunkSectionInfos = RenderSystem.getDynamicUniforms()
            .writeChunkSections(sectionInfos.toArray(new DynamicUniforms.ChunkSectionInfo[0]));
        return new ChunkSectionsToRender(blockAtlas, drawGroups, largestIndexCount, chunkSectionInfos);
    }
 
    public void endFrame() {
        this.cloudRenderer.endFrame();
    }
 
    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) {
            Iterator<BlockDestructionProgress> iterator = this.destroyingBlocks.values().iterator();
 
            while (iterator.hasNext()) {
                BlockDestructionProgress block = iterator.next();
                int updatedRenderTick = block.getUpdatedRenderTick();
                if (this.ticks - updatedRenderTick > 400) {
                    iterator.remove();
                    this.removeProgress(block);
                }
            }
        }
    }
 
    private void removeProgress(BlockDestructionProgress block) {
        long pos = block.getPos().asLong();
        Set<BlockDestructionProgress> progresses = this.destructionProgress.get(pos);
        progresses.remove(block);
        if (progresses.isEmpty()) {
            this.destructionProgress.remove(pos);
        }
    }
 
    private void addSkyPass(FrameGraphBuilder frame, CameraRenderState cameraState, GpuBufferSlice skyFog) {
        FogType fogType = cameraState.fogType;
        if (fogType != FogType.POWDER_SNOW && fogType != FogType.LAVA && !cameraState.entityRenderState.doesMobEffectBlockSky) {
            SkyRenderState state = this.levelRenderState.skyRenderState;
            if (state.skybox != DimensionType.Skybox.NONE) {
                SkyRenderer skyRenderer = this.skyRenderer;
                if (skyRenderer != null) {
                    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);
                                }
                            } else {
                                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 void compileSections(Camera camera) {
        ProfilerFiller profiler = Profiler.get();
        profiler.push("populateSectionsToCompile");
        RenderRegionCache cache = new RenderRegionCache();
        BlockPos cameraPosition = camera.blockPosition();
        List<SectionRenderDispatcher.RenderSection> 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())) {
                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(fadeDuration);
                } else {
                    section.setFadeDuration(0L);
                }
 
                section.setWasPreviouslyEmpty(false);
                if (rebuildSync) {
                    profiler.push("compileSectionSynchronously");
                    this.sectionRenderDispatcher.rebuildSectionSync(section, cache);
                    section.setNotDirty();
                    profiler.pop();
                } else {
                    sectionsToCompile.add(section);
                }
            }
        }
 
        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(), pos.getX() - camX, pos.getY() - camY, pos.getZ() - camZ, ARGB.colorFromFloat(1.0F, 1.0F, 1.0F, 1.0F), width
            );
            if (state.collisionShape() != null) {
                ShapeRenderer.renderShape(
                    poseStack,
                    builder,
                    state.collisionShape(),
                    pos.getX() - camX,
                    pos.getY() - camY,
                    pos.getZ() - camZ,
                    ARGB.colorFromFloat(0.4F, 0.0F, 0.0F, 0.0F),
                    width
                );
            }
 
            if (state.occlusionShape() != null) {
                ShapeRenderer.renderShape(
                    poseStack,
                    builder,
                    state.occlusionShape(),
                    pos.getX() - camX,
                    pos.getY() - camY,
                    pos.getZ() - camZ,
                    ARGB.colorFromFloat(0.4F, 0.0F, 1.0F, 0.0F),
                    width
                );
            }
 
            if (state.interactionShape() != null) {
                ShapeRenderer.renderShape(
                    poseStack,
                    builder,
                    state.interactionShape(),
                    pos.getX() - camX,
                    pos.getY() - camY,
                    pos.getZ() - camZ,
                    ARGB.colorFromFloat(0.4F, 0.0F, 0.0F, 1.0F),
                    width
                );
            }
        } else {
            ShapeRenderer.renderShape(poseStack, builder, state.shape(), pos.getX() - camX, pos.getY() - camY, pos.getZ() - camZ, color, width);
        }
    }
 
    public void blockChanged(BlockGetter level, BlockPos pos, BlockState old, BlockState current, @Block.UpdateFlags 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 entry = 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, entry);
            }
 
            entry.setProgress(progress);
            entry.updateTick(this.ticks);
            this.destructionProgress.computeIfAbsent(entry.getPos().asLong(), k -> Sets.newTreeSet()).add(entry);
        } else {
            BlockDestructionProgress removed = this.destroyingBlocks.remove(id);
            if (removed != null) {
                this.removeProgress(removed);
            }
        }
    }
 
    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 getLightCoords(BlockAndLightGetter level, BlockPos pos) {
        return getLightCoords(LevelRenderer.BrightnessGetter.DEFAULT, level, level.getBlockState(pos), pos);
    }
 
    public static int getLightCoords(LevelRenderer.BrightnessGetter brightnessGetter, BlockAndLightGetter level, BlockState state, BlockPos pos) {
        if (state.emissiveRendering(level, pos)) {
            return 15728880;
        } else {
            int packedBrightness = brightnessGetter.packedBrightness(level, pos);
            int block = LightCoordsUtil.block(packedBrightness);
            int blockSelfEmission = state.getLightEmission();
            return block < blockSelfEmission ? LightCoordsUtil.withBlock(packedBrightness, blockSelfEmission) : packedBrightness;
        }
    }
 
    public boolean isSectionCompiledAndVisible(BlockPos blockPos) {
        SectionRenderDispatcher.RenderSection renderSection = this.viewArea.getRenderSectionAt(blockPos);
        return renderSection != null && renderSection.sectionMesh.get() != CompiledSectionMesh.UNCOMPILED
            ? renderSection.getVisibility(Util.getMillis()) >= 0.3F
            : false;
    }
 
    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<SectionRenderDispatcher.RenderSection> getVisibleSections() {
        return this.visibleSections;
    }
 
    @VisibleForDebug
    public SectionOcclusionGraph getSectionOcclusionGraph() {
        return this.sectionOcclusionGraph;
    }
 
    public CloudRenderer getCloudRenderer() {
        return this.cloudRenderer;
    }
 
    public Gizmos.TemporaryCollection collectPerFrameGizmos() {
        return Gizmos.withCollector(this.collectedGizmos);
    }
 
    private void finalizeGizmoCollection() {
        DrawableGizmoPrimitives standardPrimitives = new DrawableGizmoPrimitives();
        DrawableGizmoPrimitives alwaysOnTopPrimitives = new DrawableGizmoPrimitives();
        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()) {
            instance.gizmo().emit(instance.isAlwaysOnTop() ? alwaysOnTopPrimitives : standardPrimitives, instance.getAlphaMultiplier(currentMillis));
        }
 
        this.finalizedGizmos = new LevelRenderer.FinalizedGizmos(standardPrimitives, alwaysOnTopPrimitives);
    }
 
    @FunctionalInterface
    @OnlyIn(Dist.CLIENT)
    public interface BrightnessGetter {
        LevelRenderer.BrightnessGetter DEFAULT = (level, pos) -> {
            int sky = level.getBrightness(LightLayer.SKY, pos);
            int block = level.getBrightness(LightLayer.BLOCK, pos);
            return LightCoordsUtil.pack(block, sky);
        };
 
        int packedBrightness(BlockAndLightGetter level, BlockPos pos);
    }
 
    @OnlyIn(Dist.CLIENT)
    private record FinalizedGizmos(DrawableGizmoPrimitives standardPrimitives, DrawableGizmoPrimitives alwaysOnTopPrimitives) {
    }
}

引用的其他类