WorldBorderRenderer.java

net.minecraft.client.renderer.WorldBorderRenderer

信息

  • 全限定名:net.minecraft.client.renderer.WorldBorderRenderer
  • 类型:public class
  • 包:net.minecraft.client.renderer
  • 源码路径:src/main/java/net/minecraft/client/renderer/WorldBorderRenderer.java
  • 起始行号:L36
  • 职责:

    TODO

字段/常量

  • FORCEFIELD_LOCATION

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

      TODO

  • needsRebuild

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

      TODO

  • lastMinX

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

      TODO

  • lastMinZ

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

      TODO

  • lastBorderMinX

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

      TODO

  • lastBorderMaxX

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

      TODO

  • lastBorderMinZ

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

      TODO

  • lastBorderMaxZ

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

      TODO

  • worldBorderBuffer

    • 类型: GpuBuffer
    • 修饰符: private final
    • 源码定位: L45
    • 说明:

      TODO

  • indices

    • 类型: RenderSystem.AutoStorageIndexBuffer
    • 修饰符: private final
    • 源码定位: L47
    • 说明:

      TODO

内部类/嵌套类型

构造器

方法

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

private void rebuildWorldBorderBuffer(WorldBorderRenderState state, double renderDistance, double cameraZ, double cameraX, float halfHeightY, float v1, float v0) @ L49

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

参数:

  • state: WorldBorderRenderState
  • renderDistance: double
  • cameraZ: double
  • cameraX: double
  • halfHeightY: float
  • v1: float
  • v0: float

说明:

TODO

public void extract(WorldBorder border, float deltaPartialTick, Vec3 cameraPos, double renderDistance, WorldBorderRenderState state) @ L97

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

参数:

  • border: WorldBorder
  • deltaPartialTick: float
  • cameraPos: Vec3
  • renderDistance: double
  • state: WorldBorderRenderState

说明:

TODO

public void render(WorldBorderRenderState state, Vec3 cameraPos, double renderDistance, double depthFar) @ L121

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

参数:

  • state: WorldBorderRenderState
  • cameraPos: Vec3
  • renderDistance: double
  • depthFar: double

说明:

TODO

public void invalidate() @ L183

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

参数:

说明:

TODO

private boolean shouldRebuildWorldBorderBuffer(WorldBorderRenderState state) @ L187

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

参数:

  • state: WorldBorderRenderState

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class WorldBorderRenderer {
    public static final Identifier FORCEFIELD_LOCATION = Identifier.withDefaultNamespace("textures/misc/forcefield.png");
    private boolean needsRebuild = true;
    private double lastMinX;
    private double lastMinZ;
    private double lastBorderMinX;
    private double lastBorderMaxX;
    private double lastBorderMinZ;
    private double lastBorderMaxZ;
    private final GpuBuffer worldBorderBuffer = RenderSystem.getDevice()
        .createBuffer(() -> "World border vertex buffer", 40, 16L * DefaultVertexFormat.POSITION_TEX.getVertexSize());
    private final RenderSystem.AutoStorageIndexBuffer indices = RenderSystem.getSequentialBuffer(VertexFormat.Mode.QUADS);
 
    private void rebuildWorldBorderBuffer(
        WorldBorderRenderState state, double renderDistance, double cameraZ, double cameraX, float halfHeightY, float v1, float v0
    ) {
        try (ByteBufferBuilder byteBufferBuilder = ByteBufferBuilder.exactlySized(DefaultVertexFormat.POSITION_TEX.getVertexSize() * 4 * 4)) {
            double borderMinX = state.minX;
            double borderMaxX = state.maxX;
            double borderMinZ = state.minZ;
            double borderMaxZ = state.maxZ;
            double minZ = Math.max((double)Mth.floor(cameraZ - renderDistance), borderMinZ);
            double maxZ = Math.min((double)Mth.ceil(cameraZ + renderDistance), borderMaxZ);
            float u0z = (Mth.floor(minZ) & 1) * 0.5F;
            float u1z = (float)(maxZ - minZ) / 2.0F;
            double minX = Math.max((double)Mth.floor(cameraX - renderDistance), borderMinX);
            double maxX = Math.min((double)Mth.ceil(cameraX + renderDistance), borderMaxX);
            float u0x = (Mth.floor(minX) & 1) * 0.5F;
            float u1x = (float)(maxX - minX) / 2.0F;
            BufferBuilder bufferBuilder = new BufferBuilder(byteBufferBuilder, VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
            bufferBuilder.addVertex(0.0F, -halfHeightY, (float)(borderMaxZ - minZ)).setUv(u0x, v1);
            bufferBuilder.addVertex((float)(maxX - minX), -halfHeightY, (float)(borderMaxZ - minZ)).setUv(u1x + u0x, v1);
            bufferBuilder.addVertex((float)(maxX - minX), halfHeightY, (float)(borderMaxZ - minZ)).setUv(u1x + u0x, v0);
            bufferBuilder.addVertex(0.0F, halfHeightY, (float)(borderMaxZ - minZ)).setUv(u0x, v0);
            bufferBuilder.addVertex(0.0F, -halfHeightY, 0.0F).setUv(u0z, v1);
            bufferBuilder.addVertex(0.0F, -halfHeightY, (float)(maxZ - minZ)).setUv(u1z + u0z, v1);
            bufferBuilder.addVertex(0.0F, halfHeightY, (float)(maxZ - minZ)).setUv(u1z + u0z, v0);
            bufferBuilder.addVertex(0.0F, halfHeightY, 0.0F).setUv(u0z, v0);
            bufferBuilder.addVertex((float)(maxX - minX), -halfHeightY, 0.0F).setUv(u0x, v1);
            bufferBuilder.addVertex(0.0F, -halfHeightY, 0.0F).setUv(u1x + u0x, v1);
            bufferBuilder.addVertex(0.0F, halfHeightY, 0.0F).setUv(u1x + u0x, v0);
            bufferBuilder.addVertex((float)(maxX - minX), halfHeightY, 0.0F).setUv(u0x, v0);
            bufferBuilder.addVertex((float)(borderMaxX - minX), -halfHeightY, (float)(maxZ - minZ)).setUv(u0z, v1);
            bufferBuilder.addVertex((float)(borderMaxX - minX), -halfHeightY, 0.0F).setUv(u1z + u0z, v1);
            bufferBuilder.addVertex((float)(borderMaxX - minX), halfHeightY, 0.0F).setUv(u1z + u0z, v0);
            bufferBuilder.addVertex((float)(borderMaxX - minX), halfHeightY, (float)(maxZ - minZ)).setUv(u0z, v0);
 
            try (MeshData meshData = bufferBuilder.buildOrThrow()) {
                RenderSystem.getDevice().createCommandEncoder().writeToBuffer(this.worldBorderBuffer.slice(), meshData.vertexBuffer());
            }
 
            this.lastBorderMinX = borderMinX;
            this.lastBorderMaxX = borderMaxX;
            this.lastBorderMinZ = borderMinZ;
            this.lastBorderMaxZ = borderMaxZ;
            this.lastMinX = minX;
            this.lastMinZ = minZ;
            this.needsRebuild = false;
        }
    }
 
    public void extract(WorldBorder border, float deltaPartialTick, Vec3 cameraPos, double renderDistance, WorldBorderRenderState state) {
        state.minX = border.getMinX(deltaPartialTick);
        state.maxX = border.getMaxX(deltaPartialTick);
        state.minZ = border.getMinZ(deltaPartialTick);
        state.maxZ = border.getMaxZ(deltaPartialTick);
        if ((
                !(cameraPos.x < state.maxX - renderDistance)
                    || !(cameraPos.x > state.minX + renderDistance)
                    || !(cameraPos.z < state.maxZ - renderDistance)
                    || !(cameraPos.z > state.minZ + renderDistance)
            )
            && !(cameraPos.x < state.minX - renderDistance)
            && !(cameraPos.x > state.maxX + renderDistance)
            && !(cameraPos.z < state.minZ - renderDistance)
            && !(cameraPos.z > state.maxZ + renderDistance)) {
            state.alpha = 1.0 - border.getDistanceToBorder(cameraPos.x, cameraPos.z) / renderDistance;
            state.alpha = Math.pow(state.alpha, 4.0);
            state.alpha = Mth.clamp(state.alpha, 0.0, 1.0);
            state.tint = border.getStatus().getColor();
        } else {
            state.alpha = 0.0;
        }
    }
 
    public void render(WorldBorderRenderState state, Vec3 cameraPos, double renderDistance, double depthFar) {
        if (!(state.alpha <= 0.0)) {
            double cameraX = cameraPos.x;
            double cameraZ = cameraPos.z;
            float halfHeightY = (float)depthFar;
            float red = ARGB.red(state.tint) / 255.0F;
            float green = ARGB.green(state.tint) / 255.0F;
            float blue = ARGB.blue(state.tint) / 255.0F;
            float offset = (float)(Util.getMillis() % 3000L) / 3000.0F;
            float v0 = (float)(-Mth.frac(cameraPos.y * 0.5));
            float v1 = v0 + halfHeightY;
            if (this.shouldRebuildWorldBorderBuffer(state)) {
                this.rebuildWorldBorderBuffer(state, renderDistance, cameraZ, cameraX, halfHeightY, v1, v0);
            }
 
            TextureManager textureManager = Minecraft.getInstance().getTextureManager();
            AbstractTexture abstractTexture = textureManager.getTexture(FORCEFIELD_LOCATION);
            RenderPipeline renderPipeline = RenderPipelines.WORLD_BORDER;
            RenderTarget mainRenderTarget = Minecraft.getInstance().getMainRenderTarget();
            RenderTarget weatherTarget = Minecraft.getInstance().levelRenderer.getWeatherTarget();
            GpuTextureView colorTexture;
            GpuTextureView depthTexture;
            if (weatherTarget != null) {
                colorTexture = weatherTarget.getColorTextureView();
                depthTexture = weatherTarget.getDepthTextureView();
            } else {
                colorTexture = mainRenderTarget.getColorTextureView();
                depthTexture = mainRenderTarget.getDepthTextureView();
            }
 
            GpuBuffer indexBuffer = this.indices.getBuffer(6);
            GpuBufferSlice dynamicTransforms = RenderSystem.getDynamicUniforms()
                .writeTransform(
                    RenderSystem.getModelViewMatrix(),
                    new Vector4f(red, green, blue, (float)state.alpha),
                    new Vector3f((float)(this.lastMinX - cameraX), (float)(-cameraPos.y), (float)(this.lastMinZ - cameraZ)),
                    new Matrix4f().translation(offset, offset, 0.0F)
                );
 
            try (RenderPass renderPass = RenderSystem.getDevice()
                    .createCommandEncoder()
                    .createRenderPass(() -> "World border", colorTexture, OptionalInt.empty(), depthTexture, OptionalDouble.empty())) {
                renderPass.setPipeline(renderPipeline);
                RenderSystem.bindDefaultUniforms(renderPass);
                renderPass.setUniform("DynamicTransforms", dynamicTransforms);
                renderPass.setIndexBuffer(indexBuffer, this.indices.type());
                renderPass.bindTexture("Sampler0", abstractTexture.getTextureView(), abstractTexture.getSampler());
                renderPass.setVertexBuffer(0, this.worldBorderBuffer);
                ArrayList<RenderPass.Draw<WorldBorderRenderer>> draws = new ArrayList<>();
 
                for (WorldBorderRenderState.DistancePerDirection distancePerDirection : state.closestBorder(cameraX, cameraZ)) {
                    if (distancePerDirection.distance() < renderDistance) {
                        int sideIndex = distancePerDirection.direction().get2DDataValue();
                        draws.add(new RenderPass.Draw<>(0, this.worldBorderBuffer, indexBuffer, this.indices.type(), 6 * sideIndex, 6, 0));
                    }
                }
 
                renderPass.drawMultipleIndexed(draws, null, null, Collections.emptyList(), this);
            }
        }
    }
 
    public void invalidate() {
        this.needsRebuild = true;
    }
 
    private boolean shouldRebuildWorldBorderBuffer(WorldBorderRenderState state) {
        return this.needsRebuild
            || state.minX != this.lastBorderMinX
            || state.minZ != this.lastBorderMinZ
            || state.maxX != this.lastBorderMaxX
            || state.maxZ != this.lastBorderMaxZ;
    }
}

引用的其他类

  • GpuBuffer

    • 引用位置: 字段
  • RenderSystem

    • 引用位置: 字段/方法调用
    • 关联成员: RenderSystem.bindDefaultUniforms(), RenderSystem.getDevice(), RenderSystem.getDynamicUniforms(), RenderSystem.getModelViewMatrix(), RenderSystem.getSequentialBuffer()
  • BufferBuilder

    • 引用位置: 构造调用
    • 关联成员: BufferBuilder()
  • ByteBufferBuilder

    • 引用位置: 方法调用
    • 关联成员: ByteBufferBuilder.exactlySized()
  • Minecraft

    • 引用位置: 方法调用
    • 关联成员: Minecraft.getInstance()
  • WorldBorderRenderState

    • 引用位置: 参数
  • Identifier

    • 引用位置: 字段/方法调用
    • 关联成员: Identifier.withDefaultNamespace()
  • ARGB

    • 引用位置: 方法调用
    • 关联成员: ARGB.blue(), ARGB.green(), ARGB.red()
  • Mth

    • 引用位置: 方法调用
    • 关联成员: Mth.ceil(), Mth.clamp(), Mth.floor(), Mth.frac()
  • Util

    • 引用位置: 方法调用
    • 关联成员: Util.getMillis()
  • WorldBorder

    • 引用位置: 参数
  • Vec3

    • 引用位置: 参数