QuadParticleRenderState.java

net.minecraft.client.renderer.state.level.QuadParticleRenderState

信息

  • 全限定名:net.minecraft.client.renderer.state.level.QuadParticleRenderState
  • 类型:public class
  • 包:net.minecraft.client.renderer.state.level
  • 源码路径:src/main/java/net/minecraft/client/renderer/state/level/QuadParticleRenderState.java
  • 起始行号:L30
  • 实现:ParticleGroupRenderState, SubmitNodeCollector.ParticleGroupRenderer
  • 职责:

    TODO

字段/常量

  • INITIAL_PARTICLE_CAPACITY

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

      TODO

  • FLOATS_PER_PARTICLE

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

      TODO

  • INTS_PER_PARTICLE

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

      TODO

  • particles

    • 类型: Map<SingleQuadParticle.Layer,QuadParticleRenderState.Storage>
    • 修饰符: private final
    • 源码定位: L34
    • 说明:

      TODO

  • particleCount

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

      TODO

内部类/嵌套类型

  • net.minecraft.client.renderer.state.level.QuadParticleRenderState.ParticleConsumer

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

      TODO

  • net.minecraft.client.renderer.state.level.QuadParticleRenderState.PreparedBuffers

    • 类型: record
    • 修饰符: public
    • 源码定位: L196
    • 说明:

      TODO

  • net.minecraft.client.renderer.state.level.QuadParticleRenderState.PreparedLayer

    • 类型: record
    • 修饰符: public
    • 源码定位: L200
    • 说明:

      TODO

  • net.minecraft.client.renderer.state.level.QuadParticleRenderState.Storage

    • 类型: class
    • 修饰符: private static
    • 源码定位: L204
    • 说明:

      TODO

构造器

方法

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

public void add(SingleQuadParticle.Layer layer, float x, float y, float z, float xRot, float yRot, float zRot, float wRot, float scale, float u0, float u1, float v0, float v1, int color, int lightCoords) @ L37

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

参数:

  • layer: SingleQuadParticle.Layer
  • x: float
  • y: float
  • z: float
  • xRot: float
  • yRot: float
  • zRot: float
  • wRot: float
  • scale: float
  • u0: float
  • u1: float
  • v0: float
  • v1: float
  • color: int
  • lightCoords: int

说明:

TODO

public void clear() @ L60

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

参数:

说明:

TODO

public boolean isEmpty() @ L66

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

参数:

说明:

TODO

public QuadParticleRenderState.PreparedBuffers prepare(ParticleFeatureRenderer.ParticleBufferCache cachedBuffer, boolean translucent) @ L71

  • 方法名:prepare
  • 源码定位:L71
  • 返回类型:QuadParticleRenderState.PreparedBuffers
  • 修饰符:public

参数:

  • cachedBuffer: ParticleFeatureRenderer.ParticleBufferCache
  • translucent: boolean

说明:

TODO

public void render(QuadParticleRenderState.PreparedBuffers preparedBuffers, ParticleFeatureRenderer.ParticleBufferCache bufferCache, RenderPass renderPass, TextureManager textureManager) @ L116

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

参数:

  • preparedBuffers: QuadParticleRenderState.PreparedBuffers
  • bufferCache: ParticleFeatureRenderer.ParticleBufferCache
  • renderPass: RenderPass
  • textureManager: TextureManager

说明:

TODO

protected void renderRotatedQuad(VertexConsumer builder, float x, float y, float z, float xRot, float yRot, float zRot, float wRot, float scale, float u0, float u1, float v0, float v1, int color, int lightCoords) @ L136

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

参数:

  • builder: VertexConsumer
  • x: float
  • y: float
  • z: float
  • xRot: float
  • yRot: float
  • zRot: float
  • wRot: float
  • scale: float
  • u0: float
  • u1: float
  • v0: float
  • v1: float
  • color: int
  • lightCoords: int

说明:

TODO

private void renderVertex(VertexConsumer builder, Quaternionf rotation, float x, float y, float z, float nx, float ny, float scale, float u, float v, int color, int lightCoords) @ L160

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

参数:

  • builder: VertexConsumer
  • rotation: Quaternionf
  • x: float
  • y: float
  • z: float
  • nx: float
  • ny: float
  • scale: float
  • u: float
  • v: float
  • color: int
  • lightCoords: int

说明:

TODO

public void submit(SubmitNodeCollector submitNodeCollector, CameraRenderState camera) @ L167

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

参数:

  • submitNodeCollector: SubmitNodeCollector
  • camera: CameraRenderState

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class QuadParticleRenderState implements ParticleGroupRenderState, SubmitNodeCollector.ParticleGroupRenderer {
    private static final int INITIAL_PARTICLE_CAPACITY = 1024;
    private static final int FLOATS_PER_PARTICLE = 12;
    private static final int INTS_PER_PARTICLE = 2;
    private final Map<SingleQuadParticle.Layer, QuadParticleRenderState.Storage> particles = new HashMap<>();
    private int particleCount;
 
    public void add(
        SingleQuadParticle.Layer layer,
        float x,
        float y,
        float z,
        float xRot,
        float yRot,
        float zRot,
        float wRot,
        float scale,
        float u0,
        float u1,
        float v0,
        float v1,
        int color,
        int lightCoords
    ) {
        this.particles
            .computeIfAbsent(layer, ignored -> new QuadParticleRenderState.Storage())
            .add(x, y, z, xRot, yRot, zRot, wRot, scale, u0, u1, v0, v1, color, lightCoords);
        this.particleCount++;
    }
 
    @Override
    public void clear() {
        this.particles.values().forEach(QuadParticleRenderState.Storage::clear);
        this.particleCount = 0;
    }
 
    @Override
    public boolean isEmpty() {
        return this.particleCount == 0;
    }
 
    @Override
    public QuadParticleRenderState.@Nullable PreparedBuffers prepare(ParticleFeatureRenderer.ParticleBufferCache cachedBuffer, boolean translucent) {
        if (this.isEmpty()) {
            return null;
        } else {
            int vertexCount = this.particleCount * 4;
 
            Object var14;
            try (ByteBufferBuilder builder = ByteBufferBuilder.exactlySized(vertexCount * DefaultVertexFormat.PARTICLE.getVertexSize())) {
                BufferBuilder bufferBuilder = new BufferBuilder(builder, VertexFormat.Mode.QUADS, DefaultVertexFormat.PARTICLE);
                Map<SingleQuadParticle.Layer, QuadParticleRenderState.PreparedLayer> preparedLayers = new HashMap<>();
                int offset = 0;
 
                for (Entry<SingleQuadParticle.Layer, QuadParticleRenderState.Storage> entry : this.particles.entrySet()) {
                    if (entry.getKey().translucent() == translucent) {
                        entry.getValue()
                            .forEachParticle(
                                (x, y, z, xRot, yRot, zRot, wRot, scale, u0, u1, v0, v1, color, lightCoords) -> this.renderRotatedQuad(
                                    bufferBuilder, x, y, z, xRot, yRot, zRot, wRot, scale, u0, u1, v0, v1, color, lightCoords
                                )
                            );
                        if (entry.getValue().count() > 0) {
                            preparedLayers.put(entry.getKey(), new QuadParticleRenderState.PreparedLayer(offset, entry.getValue().count() * 6));
                        }
 
                        offset += entry.getValue().count() * 4;
                    }
                }
 
                MeshData mesh = bufferBuilder.build();
                if (mesh != null) {
                    cachedBuffer.write(mesh.vertexBuffer());
                    RenderSystem.getSequentialBuffer(VertexFormat.Mode.QUADS).getBuffer(mesh.drawState().indexCount());
                    GpuBufferSlice dynamicTransforms = RenderSystem.getDynamicUniforms()
                        .writeTransform(RenderSystem.getModelViewMatrix(), new Vector4f(1.0F, 1.0F, 1.0F, 1.0F), new Vector3f(), new Matrix4f());
                    return new QuadParticleRenderState.PreparedBuffers(mesh.drawState().indexCount(), dynamicTransforms, preparedLayers);
                }
 
                var14 = null;
            }
 
            return (QuadParticleRenderState.PreparedBuffers)var14;
        }
    }
 
    @Override
    public void render(
        QuadParticleRenderState.PreparedBuffers preparedBuffers,
        ParticleFeatureRenderer.ParticleBufferCache bufferCache,
        RenderPass renderPass,
        TextureManager textureManager
    ) {
        RenderSystem.AutoStorageIndexBuffer indexBuffer = RenderSystem.getSequentialBuffer(VertexFormat.Mode.QUADS);
        renderPass.setVertexBuffer(0, bufferCache.get());
        renderPass.setIndexBuffer(indexBuffer.getBuffer(preparedBuffers.indexCount), indexBuffer.type());
        renderPass.setUniform("DynamicTransforms", preparedBuffers.dynamicTransforms);
 
        for (Entry<SingleQuadParticle.Layer, QuadParticleRenderState.PreparedLayer> entry : preparedBuffers.layers.entrySet()) {
            renderPass.setPipeline(entry.getKey().pipeline());
            AbstractTexture texture = textureManager.getTexture(entry.getKey().textureAtlasLocation());
            renderPass.bindTexture("Sampler0", texture.getTextureView(), texture.getSampler());
            renderPass.drawIndexed(entry.getValue().vertexOffset, 0, entry.getValue().indexCount, 1);
        }
    }
 
    protected void renderRotatedQuad(
        VertexConsumer builder,
        float x,
        float y,
        float z,
        float xRot,
        float yRot,
        float zRot,
        float wRot,
        float scale,
        float u0,
        float u1,
        float v0,
        float v1,
        int color,
        int lightCoords
    ) {
        Quaternionf rotation = new Quaternionf(xRot, yRot, zRot, wRot);
        this.renderVertex(builder, rotation, x, y, z, 1.0F, -1.0F, scale, u1, v1, color, lightCoords);
        this.renderVertex(builder, rotation, x, y, z, 1.0F, 1.0F, scale, u1, v0, color, lightCoords);
        this.renderVertex(builder, rotation, x, y, z, -1.0F, 1.0F, scale, u0, v0, color, lightCoords);
        this.renderVertex(builder, rotation, x, y, z, -1.0F, -1.0F, scale, u0, v1, color, lightCoords);
    }
 
    private void renderVertex(
        VertexConsumer builder, Quaternionf rotation, float x, float y, float z, float nx, float ny, float scale, float u, float v, int color, int lightCoords
    ) {
        Vector3f scratch = new Vector3f(nx, ny, 0.0F).rotate(rotation).mul(scale).add(x, y, z);
        builder.addVertex(scratch.x(), scratch.y(), scratch.z()).setUv(u, v).setColor(color).setLight(lightCoords);
    }
 
    @Override
    public void submit(SubmitNodeCollector submitNodeCollector, CameraRenderState camera) {
        if (this.particleCount > 0) {
            submitNodeCollector.submitParticleGroup(this);
        }
    }
 
    @FunctionalInterface
    @OnlyIn(Dist.CLIENT)
    public interface ParticleConsumer {
        void consume(
            final float x,
            final float y,
            final float z,
            final float xRot,
            final float yRot,
            final float zRot,
            final float wRot,
            final float scale,
            final float u0,
            final float u1,
            final float v0,
            final float v1,
            final int color,
            final int lightCoords
        );
    }
 
    @OnlyIn(Dist.CLIENT)
    public record PreparedBuffers(int indexCount, GpuBufferSlice dynamicTransforms, Map<SingleQuadParticle.Layer, QuadParticleRenderState.PreparedLayer> layers) {
    }
 
    @OnlyIn(Dist.CLIENT)
    public record PreparedLayer(int vertexOffset, int indexCount) {
    }
 
    @OnlyIn(Dist.CLIENT)
    private static class Storage {
        private int capacity = 1024;
        private float[] floatValues = new float[12288];
        private int[] intValues = new int[2048];
        private int currentParticleIndex;
 
        public void add(
            float x,
            float y,
            float z,
            float xRot,
            float yRot,
            float zRot,
            float wRot,
            float scale,
            float u0,
            float u1,
            float v0,
            float v1,
            int color,
            int lightCoords
        ) {
            if (this.currentParticleIndex >= this.capacity) {
                this.grow();
            }
 
            int index = this.currentParticleIndex * 12;
            this.floatValues[index++] = x;
            this.floatValues[index++] = y;
            this.floatValues[index++] = z;
            this.floatValues[index++] = xRot;
            this.floatValues[index++] = yRot;
            this.floatValues[index++] = zRot;
            this.floatValues[index++] = wRot;
            this.floatValues[index++] = scale;
            this.floatValues[index++] = u0;
            this.floatValues[index++] = u1;
            this.floatValues[index++] = v0;
            this.floatValues[index] = v1;
            index = this.currentParticleIndex * 2;
            this.intValues[index++] = color;
            this.intValues[index] = lightCoords;
            this.currentParticleIndex++;
        }
 
        public void forEachParticle(QuadParticleRenderState.ParticleConsumer consumer) {
            for (int particleIndex = 0; particleIndex < this.currentParticleIndex; particleIndex++) {
                int floatIndex = particleIndex * 12;
                int intIndex = particleIndex * 2;
                consumer.consume(
                    this.floatValues[floatIndex++],
                    this.floatValues[floatIndex++],
                    this.floatValues[floatIndex++],
                    this.floatValues[floatIndex++],
                    this.floatValues[floatIndex++],
                    this.floatValues[floatIndex++],
                    this.floatValues[floatIndex++],
                    this.floatValues[floatIndex++],
                    this.floatValues[floatIndex++],
                    this.floatValues[floatIndex++],
                    this.floatValues[floatIndex++],
                    this.floatValues[floatIndex],
                    this.intValues[intIndex++],
                    this.intValues[intIndex]
                );
            }
        }
 
        public void clear() {
            this.currentParticleIndex = 0;
        }
 
        private void grow() {
            this.capacity *= 2;
            this.floatValues = Arrays.copyOf(this.floatValues, this.capacity * 12);
            this.intValues = Arrays.copyOf(this.intValues, this.capacity * 2);
        }
 
        public int count() {
            return this.currentParticleIndex;
        }
    }
}

引用的其他类