GuiRenderer.java

net.minecraft.client.gui.render.GuiRenderer

信息

  • 全限定名:net.minecraft.client.gui.render.GuiRenderer
  • 类型:public class
  • 包:net.minecraft.client.gui.render
  • 源码路径:src/main/java/net/minecraft/client/gui/render/GuiRenderer.java
  • 起始行号:L74
  • 实现:AutoCloseable
  • 职责:

    TODO

字段/常量

  • LOGGER

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

      TODO

  • MAX_GUI_Z

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

      TODO

  • MIN_GUI_Z

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

      TODO

  • GUI_Z_NEAR

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

      TODO

  • GUI_3D_Z_FAR

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

      TODO

  • GUI_3D_Z_NEAR

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

      TODO

  • DEFAULT_ITEM_SIZE

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

      TODO

  • CLEAR_COLOR

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

      TODO

  • SCISSOR_COMPARATOR

    • 类型: Comparator<ScreenRectangle>
    • 修饰符: private static final
    • 源码定位: L83
    • 说明:

      TODO

  • TEXTURE_COMPARATOR

    • 类型: Comparator<TextureSetup>
    • 修饰符: private static final
    • 源码定位: L89
    • 说明:

      TODO

  • ELEMENT_SORT_COMPARATOR

    • 类型: Comparator<GuiElementRenderState>
    • 修饰符: private static final
    • 源码定位: L90
    • 说明:

      TODO

  • oversizedItemRenderers

    • 类型: Map<Object,OversizedItemRenderer>
    • 修饰符: private final
    • 源码定位: L95
    • 说明:

      TODO

  • renderState

    • 类型: GuiRenderState
    • 修饰符: private final
    • 源码定位: L96
    • 说明:

      TODO

  • draws

    • 类型: List<GuiRenderer.Draw>
    • 修饰符: private final
    • 源码定位: L97
    • 说明:

      TODO

  • meshesToDraw

    • 类型: List<GuiRenderer.MeshToDraw>
    • 修饰符: private final
    • 源码定位: L98
    • 说明:

      TODO

  • byteBufferBuilder

    • 类型: ByteBufferBuilder
    • 修饰符: private final
    • 源码定位: L99
    • 说明:

      TODO

  • vertexBuffers

    • 类型: Map<VertexFormat,MappableRingBuffer>
    • 修饰符: private final
    • 源码定位: L100
    • 说明:

      TODO

  • firstDrawIndexAfterBlur

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

      TODO

  • guiProjection

    • 类型: Projection
    • 修饰符: private final
    • 源码定位: L102
    • 说明:

      TODO

  • guiProjectionMatrixBuffer

    • 类型: ProjectionMatrixBuffer
    • 修饰符: private final
    • 源码定位: L103
    • 说明:

      TODO

  • bufferSource

    • 类型: MultiBufferSource.BufferSource
    • 修饰符: private final
    • 源码定位: L104
    • 说明:

      TODO

  • submitNodeCollector

    • 类型: SubmitNodeCollector
    • 修饰符: private final
    • 源码定位: L105
    • 说明:

      TODO

  • featureRenderDispatcher

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

      TODO

  • pictureInPictureRenderers

    • 类型: Map<Class<?extends PictureInPictureRenderState>,PictureInPictureRenderer<?>>
    • 修饰符: private final
    • 源码定位: L107
    • 说明:

      TODO

  • itemAtlas

    • 类型: GuiItemAtlas
    • 修饰符: private
    • 源码定位: L108
    • 说明:

      TODO

  • cachedGuiScale

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

      TODO

  • cubeMap

    • 类型: CubeMap
    • 修饰符: private final
    • 源码定位: L110
    • 说明:

      TODO

  • previousScissorArea

    • 类型: ScreenRectangle
    • 修饰符: private
    • 源码定位: L111
    • 说明:

      TODO

  • previousPipeline

    • 类型: RenderPipeline
    • 修饰符: private
    • 源码定位: L112
    • 说明:

      TODO

  • previousTextureSetup

    • 类型: TextureSetup
    • 修饰符: private
    • 源码定位: L113
    • 说明:

      TODO

  • bufferBuilder

    • 类型: BufferBuilder
    • 修饰符: private
    • 源码定位: L114
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.client.gui.render.GuiRenderer.Draw

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

      TODO

  • net.minecraft.client.gui.render.GuiRenderer.MeshToDraw

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

      TODO

构造器

public GuiRenderer(GuiRenderState renderState, MultiBufferSource.BufferSource bufferSource, SubmitNodeCollector submitNodeCollector, FeatureRenderDispatcher featureRenderDispatcher, List<PictureInPictureRenderer<?>> pictureInPictureRenderers) @ L116

  • 构造器名:GuiRenderer
  • 源码定位:L116
  • 修饰符:public

参数:

  • renderState: GuiRenderState
  • bufferSource: MultiBufferSource.BufferSource
  • submitNodeCollector: SubmitNodeCollector
  • featureRenderDispatcher: FeatureRenderDispatcher
  • pictureInPictureRenderers: List<PictureInPictureRenderer<?>>

说明:

TODO

方法

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

public void endFrame() @ L136

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

参数:

说明:

TODO

public void render(GpuBufferSlice fogBuffer) @ L142

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

参数:

  • fogBuffer: GpuBufferSlice

说明:

TODO

private void clearUnusedOversizedItemRenderers() @ L170

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

参数:

说明:

TODO

private void prepare() @ L185

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

参数:

说明:

TODO

private void addElementsToMeshes(GuiRenderState.TraverseRange range) @ L197

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

参数:

  • range: GuiRenderState.TraverseRange

说明:

TODO

private void draw(GpuBufferSlice fogBuffer) @ L208

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

参数:

  • fogBuffer: GpuBufferSlice

说明:

TODO

private void executeDrawRange(Supplier<String> label, RenderTarget mainRenderTarget, GpuBufferSlice fogBuffer, GpuBufferSlice dynamicTransforms, GpuBuffer indexBuffer, VertexFormat.IndexType indexType, int startIndex, int endIndex) @ L259

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

参数:

  • label: Supplier
  • mainRenderTarget: RenderTarget
  • fogBuffer: GpuBufferSlice
  • dynamicTransforms: GpuBufferSlice
  • indexBuffer: GpuBuffer
  • indexType: VertexFormat.IndexType
  • startIndex: int
  • endIndex: int

说明:

TODO

private void addElementToMesh(GuiElementRenderState elementState) @ L289

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

参数:

  • elementState: GuiElementRenderState

说明:

TODO

private void prepareText() @ L307

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

参数:

说明:

TODO

private void prepareItemElements() @ L333

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

参数:

说明:

TODO

private void preparePictureInPicture() @ L369

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

参数:

说明:

TODO

private <T extends PictureInPictureRenderState> void preparePictureInPictureState(T picturesInPictureState, int guiScale) @ L374

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

参数:

  • picturesInPictureState: T
  • guiScale: int

说明:

TODO

private void submitBlitFromItemAtlas(GuiItemRenderState itemState, GuiItemAtlas.SlotView slotView) @ L381

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

参数:

  • itemState: GuiItemRenderState
  • slotView: GuiItemAtlas.SlotView

说明:

TODO

private GuiItemAtlas prepareItemAtlas(Set<Object> itemsInFrame, int slotTextureSize) @ L403

  • 方法名:prepareItemAtlas
  • 源码定位:L403
  • 返回类型:GuiItemAtlas
  • 修饰符:private

参数:

  • itemsInFrame: Set
  • slotTextureSize: int
  • 说明:

    TODO

    private int getGuiScaleInvalidatingItemAtlasIfChanged() @ L427

    • 方法名:getGuiScaleInvalidatingItemAtlasIfChanged
    • 源码定位:L427
    • 返回类型:int
    • 修饰符:private

    参数:

    说明:

    TODO

    private void invalidateItemAtlas() @ L442

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

    参数:

    说明:

    TODO

    private void recordMesh(BufferBuilder bufferBuilder, RenderPipeline pipeline, TextureSetup textureSetup, ScreenRectangle scissorArea) @ L449

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

    参数:

    • bufferBuilder: BufferBuilder
    • pipeline: RenderPipeline
    • textureSetup: TextureSetup
    • scissorArea: ScreenRectangle

    说明:

    TODO

    private void recordDraws() @ L456

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

    参数:

    说明:

    TODO

    private void ensureVertexBufferSizes() @ L495

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

    参数:

    说明:

    TODO

    private Object2IntMap<VertexFormat> calculatedRequiredVertexBufferSizes() @ L512

    • 方法名:calculatedRequiredVertexBufferSizes
    • 源码定位:L512
    • 返回类型:Object2IntMap
    • 修饰符:private

    参数:

    说明:

    TODO

    private void executeDraw(GuiRenderer.Draw draw, RenderPass renderPass, GpuBuffer indexBuffer, VertexFormat.IndexType indexType) @ L528

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

    参数:

    • draw: GuiRenderer.Draw
    • renderPass: RenderPass
    • indexBuffer: GpuBuffer
    • indexType: VertexFormat.IndexType

    说明:

    TODO

    private BufferBuilder getBufferBuilder(RenderPipeline pipeline) @ L555

    • 方法名:getBufferBuilder
    • 源码定位:L555
    • 返回类型:BufferBuilder
    • 修饰符:private

    参数:

    • pipeline: RenderPipeline

    说明:

    TODO

    private boolean scissorChanged(ScreenRectangle newScissor, ScreenRectangle oldScissor) @ L559

    • 方法名:scissorChanged
    • 源码定位:L559
    • 返回类型:boolean
    • 修饰符:private

    参数:

    • newScissor: ScreenRectangle
    • oldScissor: ScreenRectangle

    说明:

    TODO

    private void enableScissor(ScreenRectangle rectangle, RenderPass renderPass) @ L567

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

    参数:

    • rectangle: ScreenRectangle
    • renderPass: RenderPass

    说明:

    TODO

    public void registerPanoramaTextures(TextureManager textureManager) @ L578

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

    参数:

    • textureManager: TextureManager

    说明:

    TODO

    public void close() @ L582

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

    参数:

    说明:

    TODO

    代码

    @OnlyIn(Dist.CLIENT)
    public class GuiRenderer implements AutoCloseable {
        private static final Logger LOGGER = LogUtils.getLogger();
        private static final float MAX_GUI_Z = 10000.0F;
        public static final float MIN_GUI_Z = 0.0F;
        private static final float GUI_Z_NEAR = 1000.0F;
        public static final int GUI_3D_Z_FAR = 1000;
        public static final int GUI_3D_Z_NEAR = -1000;
        public static final int DEFAULT_ITEM_SIZE = 16;
        public static final int CLEAR_COLOR = 0;
        private static final Comparator<ScreenRectangle> SCISSOR_COMPARATOR = Comparator.nullsFirst(
            Comparator.comparing(ScreenRectangle::top)
                .thenComparing(ScreenRectangle::bottom)
                .thenComparing(ScreenRectangle::left)
                .thenComparing(ScreenRectangle::right)
        );
        private static final Comparator<TextureSetup> TEXTURE_COMPARATOR = Comparator.nullsFirst(Comparator.comparing(TextureSetup::getSortKey));
        private static final Comparator<GuiElementRenderState> ELEMENT_SORT_COMPARATOR = Comparator.comparing(
                GuiElementRenderState::scissorArea, SCISSOR_COMPARATOR
            )
            .thenComparing(GuiElementRenderState::pipeline, Comparator.comparing(RenderPipeline::getSortKey))
            .thenComparing(GuiElementRenderState::textureSetup, TEXTURE_COMPARATOR);
        private final Map<Object, OversizedItemRenderer> oversizedItemRenderers = new Object2ObjectOpenHashMap<>();
        private final GuiRenderState renderState;
        private final List<GuiRenderer.Draw> draws = new ArrayList<>();
        private final List<GuiRenderer.MeshToDraw> meshesToDraw = new ArrayList<>();
        private final ByteBufferBuilder byteBufferBuilder = new ByteBufferBuilder(786432);
        private final Map<VertexFormat, MappableRingBuffer> vertexBuffers = new Object2ObjectOpenHashMap<>();
        private int firstDrawIndexAfterBlur = Integer.MAX_VALUE;
        private final Projection guiProjection = new Projection();
        private final ProjectionMatrixBuffer guiProjectionMatrixBuffer = new ProjectionMatrixBuffer("gui");
        private final MultiBufferSource.BufferSource bufferSource;
        private final SubmitNodeCollector submitNodeCollector;
        private final FeatureRenderDispatcher featureRenderDispatcher;
        private final Map<Class<? extends PictureInPictureRenderState>, PictureInPictureRenderer<?>> pictureInPictureRenderers;
        private @Nullable GuiItemAtlas itemAtlas;
        private int cachedGuiScale;
        private final CubeMap cubeMap = new CubeMap(Identifier.withDefaultNamespace("textures/gui/title/background/panorama"));
        private @Nullable ScreenRectangle previousScissorArea = null;
        private @Nullable RenderPipeline previousPipeline = null;
        private @Nullable TextureSetup previousTextureSetup = null;
        private @Nullable BufferBuilder bufferBuilder = null;
     
        public GuiRenderer(
            GuiRenderState renderState,
            MultiBufferSource.BufferSource bufferSource,
            SubmitNodeCollector submitNodeCollector,
            FeatureRenderDispatcher featureRenderDispatcher,
            List<PictureInPictureRenderer<?>> pictureInPictureRenderers
        ) {
            this.renderState = renderState;
            this.bufferSource = bufferSource;
            this.submitNodeCollector = submitNodeCollector;
            this.featureRenderDispatcher = featureRenderDispatcher;
            Builder<Class<? extends PictureInPictureRenderState>, PictureInPictureRenderer<?>> builder = ImmutableMap.builder();
     
            for (PictureInPictureRenderer<?> pictureInPictureRenderer : pictureInPictureRenderers) {
                builder.put((Class<? extends PictureInPictureRenderState>)pictureInPictureRenderer.getRenderStateClass(), pictureInPictureRenderer);
            }
     
            this.pictureInPictureRenderers = builder.buildOrThrow();
        }
     
        public void endFrame() {
            if (this.itemAtlas != null) {
                this.itemAtlas.endFrame();
            }
        }
     
        public void render(GpuBufferSlice fogBuffer) {
            ProfilerFiller profiler = Profiler.get();
            if (this.renderState.panoramaRenderState != null) {
                this.cubeMap.render(10.0F, this.renderState.panoramaRenderState.spin());
            }
     
            profiler.push("prepare");
            this.prepare();
            profiler.popPush("draw");
            this.draw(fogBuffer);
            profiler.popPush("vertexBufferRotate");
     
            for (MappableRingBuffer buffer : this.vertexBuffers.values()) {
                buffer.rotate();
            }
     
            profiler.pop();
            this.draws.clear();
            this.meshesToDraw.clear();
            this.renderState.reset();
            this.firstDrawIndexAfterBlur = Integer.MAX_VALUE;
            this.clearUnusedOversizedItemRenderers();
            if (SharedConstants.DEBUG_SHUFFLE_UI_RENDERING_ORDER) {
                RenderPipeline.updateSortKeySeed();
                TextureSetup.updateSortKeySeed();
            }
        }
     
        private void clearUnusedOversizedItemRenderers() {
            Iterator<Entry<Object, OversizedItemRenderer>> oversizedItemRendererIterator = this.oversizedItemRenderers.entrySet().iterator();
     
            while (oversizedItemRendererIterator.hasNext()) {
                Entry<Object, OversizedItemRenderer> next = oversizedItemRendererIterator.next();
                OversizedItemRenderer renderer = next.getValue();
                if (!renderer.usedOnThisFrame()) {
                    renderer.close();
                    oversizedItemRendererIterator.remove();
                } else {
                    renderer.resetUsedOnThisFrame();
                }
            }
        }
     
        private void prepare() {
            this.bufferSource.endBatch();
            this.preparePictureInPicture();
            this.prepareItemElements();
            this.prepareText();
            this.renderState.sortElements(ELEMENT_SORT_COMPARATOR);
            this.addElementsToMeshes(GuiRenderState.TraverseRange.BEFORE_BLUR);
            this.firstDrawIndexAfterBlur = this.meshesToDraw.size();
            this.addElementsToMeshes(GuiRenderState.TraverseRange.AFTER_BLUR);
            this.recordDraws();
        }
     
        private void addElementsToMeshes(GuiRenderState.TraverseRange range) {
            this.previousScissorArea = null;
            this.previousPipeline = null;
            this.previousTextureSetup = null;
            this.bufferBuilder = null;
            this.renderState.forEachElement(this::addElementToMesh, range);
            if (this.bufferBuilder != null) {
                this.recordMesh(this.bufferBuilder, this.previousPipeline, this.previousTextureSetup, this.previousScissorArea);
            }
        }
     
        private void draw(GpuBufferSlice fogBuffer) {
            if (!this.draws.isEmpty()) {
                Minecraft minecraft = Minecraft.getInstance();
                WindowRenderState windowState = minecraft.gameRenderer.getGameRenderState().windowRenderState;
                this.guiProjection
                    .setupOrtho(1000.0F, 11000.0F, (float)windowState.width / windowState.guiScale, (float)windowState.height / windowState.guiScale, true);
                RenderSystem.setProjectionMatrix(this.guiProjectionMatrixBuffer.getBuffer(this.guiProjection), ProjectionType.ORTHOGRAPHIC);
                RenderTarget mainRenderTarget = minecraft.getMainRenderTarget();
                int maxIndexCount = 0;
     
                for (GuiRenderer.Draw draw : this.draws) {
                    if (draw.indexCount > maxIndexCount) {
                        maxIndexCount = draw.indexCount;
                    }
                }
     
                RenderSystem.AutoStorageIndexBuffer autoIndices = RenderSystem.getSequentialBuffer(VertexFormat.Mode.QUADS);
                GpuBuffer indexBuffer = autoIndices.getBuffer(maxIndexCount);
                VertexFormat.IndexType indexType = autoIndices.type();
                GpuBufferSlice dynamicTransforms = RenderSystem.getDynamicUniforms()
                    .writeTransform(new Matrix4f().setTranslation(0.0F, 0.0F, -11000.0F), new Vector4f(1.0F, 1.0F, 1.0F, 1.0F), new Vector3f(), new Matrix4f());
                if (this.firstDrawIndexAfterBlur > 0) {
                    this.executeDrawRange(
                        () -> "GUI before blur",
                        mainRenderTarget,
                        fogBuffer,
                        dynamicTransforms,
                        indexBuffer,
                        indexType,
                        0,
                        Math.min(this.firstDrawIndexAfterBlur, this.draws.size())
                    );
                }
     
                if (this.draws.size() > this.firstDrawIndexAfterBlur) {
                    RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(mainRenderTarget.getDepthTexture(), 1.0);
                    minecraft.gameRenderer.processBlurEffect();
                    this.executeDrawRange(
                        () -> "GUI after blur",
                        mainRenderTarget,
                        fogBuffer,
                        dynamicTransforms,
                        indexBuffer,
                        indexType,
                        this.firstDrawIndexAfterBlur,
                        this.draws.size()
                    );
                }
            }
        }
     
        private void executeDrawRange(
            Supplier<String> label,
            RenderTarget mainRenderTarget,
            GpuBufferSlice fogBuffer,
            GpuBufferSlice dynamicTransforms,
            GpuBuffer indexBuffer,
            VertexFormat.IndexType indexType,
            int startIndex,
            int endIndex
        ) {
            try (RenderPass renderPass = RenderSystem.getDevice()
                    .createCommandEncoder()
                    .createRenderPass(
                        label,
                        mainRenderTarget.getColorTextureView(),
                        OptionalInt.empty(),
                        mainRenderTarget.useDepth ? mainRenderTarget.getDepthTextureView() : null,
                        OptionalDouble.empty()
                    )) {
                RenderSystem.bindDefaultUniforms(renderPass);
                renderPass.setUniform("Fog", fogBuffer);
                renderPass.setUniform("DynamicTransforms", dynamicTransforms);
     
                for (int i = startIndex; i < endIndex; i++) {
                    GuiRenderer.Draw draw = this.draws.get(i);
                    this.executeDraw(draw, renderPass, indexBuffer, indexType);
                }
            }
        }
     
        private void addElementToMesh(GuiElementRenderState elementState) {
            RenderPipeline pipeline = elementState.pipeline();
            TextureSetup textureSetup = elementState.textureSetup();
            ScreenRectangle scissorArea = elementState.scissorArea();
            if (pipeline != this.previousPipeline || this.scissorChanged(scissorArea, this.previousScissorArea) || !textureSetup.equals(this.previousTextureSetup)) {
                if (this.bufferBuilder != null) {
                    this.recordMesh(this.bufferBuilder, this.previousPipeline, this.previousTextureSetup, this.previousScissorArea);
                }
     
                this.bufferBuilder = this.getBufferBuilder(pipeline);
                this.previousPipeline = pipeline;
                this.previousTextureSetup = textureSetup;
                this.previousScissorArea = scissorArea;
            }
     
            elementState.buildVertices(this.bufferBuilder);
        }
     
        private void prepareText() {
            this.renderState.forEachText(text -> {
                final Matrix3x2fc pose = text.pose;
                final ScreenRectangle scissor = text.scissor;
                text.ensurePrepared().visit(new Font.GlyphVisitor() {
                    {
                        Objects.requireNonNull(GuiRenderer.this);
                    }
     
                    @Override
                    public void acceptGlyph(TextRenderable.Styled glyph) {
                        this.accept(glyph);
                    }
     
                    @Override
                    public void acceptEffect(TextRenderable effect) {
                        this.accept(effect);
                    }
     
                    private void accept(TextRenderable glyph) {
                        GuiRenderer.this.renderState.addGlyphToCurrentLayer(new GlyphRenderState(pose, glyph, scissor));
                    }
                });
            });
        }
     
        private void prepareItemElements() {
            Set<Object> itemsInFrame = this.renderState.getItemModelIdentities();
            if (!itemsInFrame.isEmpty()) {
                int guiScale = this.getGuiScaleInvalidatingItemAtlasIfChanged();
                GuiItemAtlas itemAtlas = this.prepareItemAtlas(itemsInFrame, 16 * guiScale);
                MutableBoolean hasOversizedItems = new MutableBoolean(false);
                this.renderState.forEachItem(itemState -> {
                    if (itemState.oversizedItemBounds() != null) {
                        hasOversizedItems.setTrue();
                    } else {
                        GuiItemAtlas.SlotView slotView = itemAtlas.getOrUpdate(itemState.itemStackRenderState());
                        if (slotView != null) {
                            this.submitBlitFromItemAtlas(itemState, slotView);
                        }
                    }
                });
                if (hasOversizedItems.booleanValue()) {
                    this.renderState
                        .forEachItem(
                            itemState -> {
                                if (itemState.oversizedItemBounds() != null) {
                                    TrackingItemStackRenderState itemStackRenderState = itemState.itemStackRenderState();
                                    OversizedItemRenderer oversizedItemRenderer = this.oversizedItemRenderers
                                        .computeIfAbsent(itemStackRenderState.getModelIdentity(), key -> new OversizedItemRenderer(this.bufferSource));
                                    ScreenRectangle actualItemBounds = itemState.oversizedItemBounds();
                                    OversizedItemRenderState oversizedItemRenderState = new OversizedItemRenderState(
                                        itemState, actualItemBounds.left(), actualItemBounds.top(), actualItemBounds.right(), actualItemBounds.bottom()
                                    );
                                    oversizedItemRenderer.prepare(oversizedItemRenderState, this.renderState, guiScale);
                                }
                            }
                        );
                }
            }
        }
     
        private void preparePictureInPicture() {
            int guiScale = Minecraft.getInstance().gameRenderer.getGameRenderState().windowRenderState.guiScale;
            this.renderState.forEachPictureInPicture(pictureInPictureState -> this.preparePictureInPictureState(pictureInPictureState, guiScale));
        }
     
        private <T extends PictureInPictureRenderState> void preparePictureInPictureState(T picturesInPictureState, int guiScale) {
            PictureInPictureRenderer<T> renderer = (PictureInPictureRenderer<T>)this.pictureInPictureRenderers.get(picturesInPictureState.getClass());
            if (renderer != null) {
                renderer.prepare(picturesInPictureState, this.renderState, guiScale);
            }
        }
     
        private void submitBlitFromItemAtlas(GuiItemRenderState itemState, GuiItemAtlas.SlotView slotView) {
            this.renderState
                .addBlitToCurrentLayer(
                    new BlitRenderState(
                        RenderPipelines.GUI_TEXTURED_PREMULTIPLIED_ALPHA,
                        TextureSetup.singleTexture(slotView.textureView(), RenderSystem.getSamplerCache().getRepeat(FilterMode.NEAREST)),
                        itemState.pose(),
                        itemState.x(),
                        itemState.y(),
                        itemState.x() + 16,
                        itemState.y() + 16,
                        slotView.u0(),
                        slotView.u1(),
                        slotView.v0(),
                        slotView.v1(),
                        -1,
                        itemState.scissorArea(),
                        null
                    )
                );
        }
     
        private GuiItemAtlas prepareItemAtlas(Set<Object> itemsInFrame, int slotTextureSize) {
            if (this.itemAtlas != null && this.itemAtlas.tryPrepareFor(itemsInFrame)) {
                return this.itemAtlas;
            } else {
                int newTextureSize = GuiItemAtlas.computeTextureSizeFor(slotTextureSize, itemsInFrame.size());
                if (this.itemAtlas != null && this.itemAtlas.textureSize() == newTextureSize) {
                    LOGGER.warn(
                        "Too many items ({}) in UI, some will be skipped! (Reached maximum texture size {}x{})",
                        itemsInFrame.size(),
                        newTextureSize,
                        newTextureSize
                    );
                    return this.itemAtlas;
                } else {
                    if (this.itemAtlas != null) {
                        this.itemAtlas.close();
                    }
     
                    this.itemAtlas = new GuiItemAtlas(this.submitNodeCollector, this.featureRenderDispatcher, this.bufferSource, newTextureSize, slotTextureSize);
                    return this.itemAtlas;
                }
            }
        }
     
        private int getGuiScaleInvalidatingItemAtlasIfChanged() {
            int guiScale = Minecraft.getInstance().gameRenderer.getGameRenderState().windowRenderState.guiScale;
            if (guiScale != this.cachedGuiScale) {
                this.invalidateItemAtlas();
     
                for (OversizedItemRenderer renderer : this.oversizedItemRenderers.values()) {
                    renderer.invalidateTexture();
                }
     
                this.cachedGuiScale = guiScale;
            }
     
            return guiScale;
        }
     
        private void invalidateItemAtlas() {
            if (this.itemAtlas != null) {
                this.itemAtlas.close();
                this.itemAtlas = null;
            }
        }
     
        private void recordMesh(BufferBuilder bufferBuilder, RenderPipeline pipeline, TextureSetup textureSetup, @Nullable ScreenRectangle scissorArea) {
            MeshData mesh = bufferBuilder.build();
            if (mesh != null) {
                this.meshesToDraw.add(new GuiRenderer.MeshToDraw(mesh, pipeline, textureSetup, scissorArea));
            }
        }
     
        private void recordDraws() {
            this.ensureVertexBufferSizes();
            CommandEncoder commandEncoder = RenderSystem.getDevice().createCommandEncoder();
            Object2IntMap<VertexFormat> offsets = new Object2IntOpenHashMap<>();
     
            for (GuiRenderer.MeshToDraw meshToDraw : this.meshesToDraw) {
                MeshData mesh = meshToDraw.mesh;
                MeshData.DrawState drawState = mesh.drawState();
                VertexFormat format = drawState.format();
                MappableRingBuffer vertexBuffer = this.vertexBuffers.get(format);
                if (!offsets.containsKey(format)) {
                    offsets.put(format, 0);
                }
     
                ByteBuffer meshVertexBuffer = mesh.vertexBuffer();
                int meshBufferSize = meshVertexBuffer.remaining();
                int offset = offsets.getInt(format);
     
                try (GpuBuffer.MappedView mappedView = commandEncoder.mapBuffer(vertexBuffer.currentBuffer().slice(offset, meshBufferSize), false, true)) {
                    MemoryUtil.memCopy(meshVertexBuffer, mappedView.data());
                }
     
                offsets.put(format, offset + meshBufferSize);
                this.draws
                    .add(
                        new GuiRenderer.Draw(
                            vertexBuffer.currentBuffer(),
                            offset / format.getVertexSize(),
                            drawState.mode(),
                            drawState.indexCount(),
                            meshToDraw.pipeline,
                            meshToDraw.textureSetup,
                            meshToDraw.scissorArea
                        )
                    );
                meshToDraw.close();
            }
        }
     
        private void ensureVertexBufferSizes() {
            Object2IntMap<VertexFormat> requiredSizes = this.calculatedRequiredVertexBufferSizes();
     
            for (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry<VertexFormat> entry : requiredSizes.object2IntEntrySet()) {
                VertexFormat vertexFormat = entry.getKey();
                int requiredSize = entry.getIntValue();
                MappableRingBuffer vertexBuffer = this.vertexBuffers.get(vertexFormat);
                if (vertexBuffer == null || vertexBuffer.size() < requiredSize) {
                    if (vertexBuffer != null) {
                        vertexBuffer.close();
                    }
     
                    this.vertexBuffers.put(vertexFormat, new MappableRingBuffer(() -> "GUI vertex buffer for " + vertexFormat, 34, requiredSize));
                }
            }
        }
     
        private Object2IntMap<VertexFormat> calculatedRequiredVertexBufferSizes() {
            Object2IntMap<VertexFormat> requiredVertexBufferSizes = new Object2IntOpenHashMap<>();
     
            for (GuiRenderer.MeshToDraw meshToDraw : this.meshesToDraw) {
                MeshData.DrawState drawState = meshToDraw.mesh.drawState();
                VertexFormat format = drawState.format();
                if (!requiredVertexBufferSizes.containsKey(format)) {
                    requiredVertexBufferSizes.put(format, 0);
                }
     
                requiredVertexBufferSizes.put(format, requiredVertexBufferSizes.getInt(format) + drawState.vertexCount() * format.getVertexSize());
            }
     
            return requiredVertexBufferSizes;
        }
     
        private void executeDraw(GuiRenderer.Draw draw, RenderPass renderPass, GpuBuffer indexBuffer, VertexFormat.IndexType indexType) {
            RenderPipeline pipeline = draw.pipeline();
            renderPass.setPipeline(pipeline);
            renderPass.setVertexBuffer(0, draw.vertexBuffer);
            ScreenRectangle scissorArea = draw.scissorArea();
            if (scissorArea != null) {
                this.enableScissor(scissorArea, renderPass);
            } else {
                renderPass.disableScissor();
            }
     
            if (draw.textureSetup.texure0() != null) {
                renderPass.bindTexture("Sampler0", draw.textureSetup.texure0(), draw.textureSetup.sampler0());
            }
     
            if (draw.textureSetup.texure1() != null) {
                renderPass.bindTexture("Sampler1", draw.textureSetup.texure1(), draw.textureSetup.sampler1());
            }
     
            if (draw.textureSetup.texure2() != null) {
                renderPass.bindTexture("Sampler2", draw.textureSetup.texure2(), draw.textureSetup.sampler2());
            }
     
            renderPass.setIndexBuffer(indexBuffer, indexType);
            renderPass.drawIndexed(draw.baseVertex, 0, draw.indexCount, 1);
        }
     
        private BufferBuilder getBufferBuilder(RenderPipeline pipeline) {
            return new BufferBuilder(this.byteBufferBuilder, pipeline.getVertexFormatMode(), pipeline.getVertexFormat());
        }
     
        private boolean scissorChanged(@Nullable ScreenRectangle newScissor, @Nullable ScreenRectangle oldScissor) {
            if (newScissor == oldScissor) {
                return false;
            } else {
                return newScissor != null ? !newScissor.equals(oldScissor) : true;
            }
        }
     
        private void enableScissor(ScreenRectangle rectangle, RenderPass renderPass) {
            WindowRenderState windowState = Minecraft.getInstance().gameRenderer.getGameRenderState().windowRenderState;
            int windowHeight = windowState.height;
            int guiScale = windowState.guiScale;
            double left = rectangle.left() * guiScale;
            double bottom = windowHeight - rectangle.bottom() * guiScale;
            double width = rectangle.width() * guiScale;
            double height = rectangle.height() * guiScale;
            renderPass.enableScissor((int)left, (int)bottom, Math.max(0, (int)width), Math.max(0, (int)height));
        }
     
        public void registerPanoramaTextures(TextureManager textureManager) {
            this.cubeMap.registerTextures(textureManager);
        }
     
        @Override
        public void close() {
            this.byteBufferBuilder.close();
            if (this.itemAtlas != null) {
                this.itemAtlas.close();
                this.itemAtlas = null;
            }
     
            this.pictureInPictureRenderers.values().forEach(PictureInPictureRenderer::close);
            this.guiProjectionMatrixBuffer.close();
     
            for (MappableRingBuffer buffer : this.vertexBuffers.values()) {
                buffer.close();
            }
     
            this.oversizedItemRenderers.values().forEach(PictureInPictureRenderer::close);
            this.cubeMap.close();
        }
     
        @OnlyIn(Dist.CLIENT)
        private record Draw(
            GpuBuffer vertexBuffer,
            int baseVertex,
            VertexFormat.Mode mode,
            int indexCount,
            RenderPipeline pipeline,
            TextureSetup textureSetup,
            @Nullable ScreenRectangle scissorArea
        ) {
        }
     
        @OnlyIn(Dist.CLIENT)
        private record MeshToDraw(MeshData mesh, RenderPipeline pipeline, TextureSetup textureSetup, @Nullable ScreenRectangle scissorArea)
            implements AutoCloseable {
            @Override
            public void close() {
                this.mesh.close();
            }
        }
    }

    引用的其他类