From a1b1b1e42641516735d922fcc3717c7c76cd199f Mon Sep 17 00:00:00 2001 From: Grauly Date: Fri, 26 Sep 2025 00:52:57 +0200 Subject: [PATCH 1/3] fix: fix ParticleRendererRegistryTests Previous implementation of the tests did not require the API to actually be functional, as long as the particle was a BillboardParticle --- .../client/ParticleRendererRegistryTests.java | 140 ++++++++++++++++-- 1 file changed, 130 insertions(+), 10 deletions(-) diff --git a/fabric-particles-v1/src/testmodClient/java/net/fabricmc/fabric/test/particle/client/ParticleRendererRegistryTests.java b/fabric-particles-v1/src/testmodClient/java/net/fabricmc/fabric/test/particle/client/ParticleRendererRegistryTests.java index ef947984a6..36d8621f52 100644 --- a/fabric-particles-v1/src/testmodClient/java/net/fabricmc/fabric/test/particle/client/ParticleRendererRegistryTests.java +++ b/fabric-particles-v1/src/testmodClient/java/net/fabricmc/fabric/test/particle/client/ParticleRendererRegistryTests.java @@ -18,7 +18,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.particle.BillboardParticle; import net.minecraft.client.particle.BillboardParticleSubmittable; import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.ParticleFactory; @@ -27,14 +26,24 @@ import net.minecraft.client.particle.ParticleTextureSheet; import net.minecraft.client.render.Camera; import net.minecraft.client.render.Frustum; +import net.minecraft.client.render.LightmapTextureManager; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.Submittable; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.command.OrderedRenderCommandQueue; +import net.minecraft.client.render.state.CameraRenderState; import net.minecraft.client.texture.Sprite; +import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; import net.minecraft.particle.SimpleParticleType; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; +import net.minecraft.util.Atlases; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.random.Random; import net.fabricmc.api.ClientModInitializer; @@ -45,6 +54,11 @@ import net.fabricmc.fabric.api.client.particle.v1.ParticleRendererRegistry; import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes; +import org.joml.Vector3f; + +import java.util.Arrays; +import java.util.Iterator; + public class ParticleRendererRegistryTests implements ClientModInitializer { private static final Identifier PARTICLE_ID = Identifier.of("fabric-particles-v1-testmod", "test"); private static final SimpleParticleType TEST_PARTICLE_TYPE = FabricParticleTypes.simple(); @@ -78,21 +92,20 @@ public void onInitializeClient() { }))); } - private record TestParticleFactory(FabricSpriteProvider spriteProvider) implements ParticleFactory { + private record TestParticleFactory( + FabricSpriteProvider spriteProvider) implements ParticleFactory { @Override public Particle createParticle(SimpleParticleType parameters, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, Random random) { return new TestParticle(world, x, y, z, velocityX, velocityY, velocityZ, spriteProvider.getSprite(random)); } } - private static class TestParticle extends BillboardParticle { - TestParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, Sprite sprite) { - super(world, x, y, z, velocityX, velocityY, velocityZ, sprite); - } + private static class TestParticle extends Particle { + private final Sprite sprite; - @Override - protected RenderType getRenderType() { - return RenderType.field_62640; + TestParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, Sprite sprite) { + super(world, x, y, z, velocityX, velocityY, velocityZ); + this.sprite = sprite; } @Override @@ -103,10 +116,17 @@ public ParticleTextureSheet textureSheet() { private boolean intersectPoint(Frustum frustum) { return frustum.intersectPoint(x, y, z); } + + public void render(TestParticleSubmittable submittable, Camera camera, float tickProgress) { + double frameX = MathHelper.lerp(tickProgress, lastX, x) - camera.getPos().x; + double frameY = MathHelper.lerp(tickProgress, lastY, y) - camera.getPos().y; + double frameZ = MathHelper.lerp(tickProgress, lastZ, z) - camera.getPos().z; + submittable.addParticle(frameX, frameY, frameZ); + } } private static class TestParticleRenderer extends ParticleRenderer { - final BillboardParticleSubmittable submittable = new BillboardParticleSubmittable(); + final TestParticleSubmittable submittable = new TestParticleSubmittable(); TestParticleRenderer(ParticleManager particleManager) { super(particleManager); @@ -125,4 +145,104 @@ public Submittable render(Frustum frustum, Camera camera, float tickProgress) { return submittable; } } + + private static class TestParticleSubmittable implements Submittable { + private final TestParticlePositions positions = new TestParticlePositions(); + + @Override + public void submit(OrderedRenderCommandQueue queue, CameraRenderState cameraRenderState) { + MatrixStack matrices = new MatrixStack(); + + for (int i = 0; i < positions.getStoredPoints(); i++) { + matrices.push(); + Vec3d position = positions.getPoint(i); + + matrices.translate(position); + + queue.submitCustom( + matrices, + //help: find a better way to do this + RenderLayer.getEntityCutout(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE), + (matrixEntry, vertexConsumer) -> { + //yes, this will render the entire atlas + //also is in the shape of a rectangle, a shape impossible to create with a BillboardParticle + vertexConsumer.vertex(matrixEntry, 0.5f, 0.0f, -1.0f) + .texture(1f, 1f) + .light(LightmapTextureManager.MAX_LIGHT_COORDINATE) + .overlay(OverlayTexture.DEFAULT_UV) + .color(-1) + .normal(matrixEntry, 0f, 1f, 0f); + vertexConsumer.vertex(matrixEntry, 0.5f, 0.0f, 1.0f) + .texture(0f, 1f) + .light(LightmapTextureManager.MAX_LIGHT_COORDINATE) + .overlay(OverlayTexture.DEFAULT_UV) + .color(-1) + .normal(matrixEntry, 0f, 1f, 0f); + vertexConsumer.vertex(matrixEntry, -0.5f, 0.0f, 1.0f) + .texture(0f, 0f) + .light(LightmapTextureManager.MAX_LIGHT_COORDINATE) + .overlay(OverlayTexture.DEFAULT_UV) + .color(-1) + .normal(matrixEntry, 0f, 1f, 0f); + vertexConsumer.vertex(matrixEntry, -0.5f, 0.0f, -1.0f) + .texture(1f, 0f) + .light(LightmapTextureManager.MAX_LIGHT_COORDINATE) + .overlay(OverlayTexture.DEFAULT_UV) + .color(-1) + .normal(matrixEntry, 0f, 1f, 0f); + } + ); + matrices.pop(); + } + } + + @Override + public void onFrameEnd() { + positions.reset(); + } + + public void addParticle(double x, double y, double z) { + positions.addPoint(x, y, z); + } + } + + private static class TestParticlePositions { + //note: this could be any kind of data, see BillboardParticleSubmittable for a more involved example + private int maxPoints = 128; + private double[] positionData = new double[maxPoints * 3]; + private int nextVertexIndex = 0; + + public void addPoint(double x, double y, double z) { + if (nextVertexIndex >= maxPoints) { + increaseCapacity(); + } + int currentIndex = nextVertexIndex * 3; + positionData[currentIndex++] = x; + positionData[currentIndex++] = y; + positionData[currentIndex] = z; + ++nextVertexIndex; + } + + public Vec3d getPoint(int index) { + int lookupIndex = index * 3; + return new Vec3d( + positionData[lookupIndex++], + positionData[lookupIndex++], + positionData[lookupIndex] + ); + } + + public int getStoredPoints() { + return nextVertexIndex + 1; + } + + public void reset() { + nextVertexIndex = 0; + } + + private void increaseCapacity() { + maxPoints *= 2; + positionData = Arrays.copyOf(positionData, maxPoints * 3); + } + } } From e7b451760124a57d564ede0ef9b371baa0cd5f9a Mon Sep 17 00:00:00 2001 From: Grauly Date: Fri, 26 Sep 2025 01:06:53 +0200 Subject: [PATCH 2/3] chore: cleanup checkstyle issues --- .../client/ParticleRendererRegistryTests.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/fabric-particles-v1/src/testmodClient/java/net/fabricmc/fabric/test/particle/client/ParticleRendererRegistryTests.java b/fabric-particles-v1/src/testmodClient/java/net/fabricmc/fabric/test/particle/client/ParticleRendererRegistryTests.java index 36d8621f52..eedca27966 100644 --- a/fabric-particles-v1/src/testmodClient/java/net/fabricmc/fabric/test/particle/client/ParticleRendererRegistryTests.java +++ b/fabric-particles-v1/src/testmodClient/java/net/fabricmc/fabric/test/particle/client/ParticleRendererRegistryTests.java @@ -16,9 +16,10 @@ package net.fabricmc.fabric.test.particle.client; +import java.util.Arrays; + import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.particle.BillboardParticleSubmittable; import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.ParticleFactory; import net.minecraft.client.particle.ParticleManager; @@ -30,7 +31,6 @@ import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.Submittable; -import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.command.OrderedRenderCommandQueue; import net.minecraft.client.render.state.CameraRenderState; import net.minecraft.client.texture.Sprite; @@ -40,7 +40,6 @@ import net.minecraft.particle.SimpleParticleType; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; -import net.minecraft.util.Atlases; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -54,11 +53,6 @@ import net.fabricmc.fabric.api.client.particle.v1.ParticleRendererRegistry; import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes; -import org.joml.Vector3f; - -import java.util.Arrays; -import java.util.Iterator; - public class ParticleRendererRegistryTests implements ClientModInitializer { private static final Identifier PARTICLE_ID = Identifier.of("fabric-particles-v1-testmod", "test"); private static final SimpleParticleType TEST_PARTICLE_TYPE = FabricParticleTypes.simple(); @@ -216,6 +210,7 @@ public void addPoint(double x, double y, double z) { if (nextVertexIndex >= maxPoints) { increaseCapacity(); } + int currentIndex = nextVertexIndex * 3; positionData[currentIndex++] = x; positionData[currentIndex++] = y; From 8a94571bbd7d8306f7e9547a0203e228e83226c4 Mon Sep 17 00:00:00 2001 From: Grauly Date: Fri, 26 Sep 2025 01:35:30 +0200 Subject: [PATCH 3/3] refactor: remove unused sprite variable --- .../particle/client/ParticleRendererRegistryTests.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fabric-particles-v1/src/testmodClient/java/net/fabricmc/fabric/test/particle/client/ParticleRendererRegistryTests.java b/fabric-particles-v1/src/testmodClient/java/net/fabricmc/fabric/test/particle/client/ParticleRendererRegistryTests.java index eedca27966..3a6735d5bd 100644 --- a/fabric-particles-v1/src/testmodClient/java/net/fabricmc/fabric/test/particle/client/ParticleRendererRegistryTests.java +++ b/fabric-particles-v1/src/testmodClient/java/net/fabricmc/fabric/test/particle/client/ParticleRendererRegistryTests.java @@ -33,7 +33,6 @@ import net.minecraft.client.render.Submittable; import net.minecraft.client.render.command.OrderedRenderCommandQueue; import net.minecraft.client.render.state.CameraRenderState; -import net.minecraft.client.texture.Sprite; import net.minecraft.client.texture.SpriteAtlasTexture; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; @@ -90,16 +89,13 @@ private record TestParticleFactory( FabricSpriteProvider spriteProvider) implements ParticleFactory { @Override public Particle createParticle(SimpleParticleType parameters, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, Random random) { - return new TestParticle(world, x, y, z, velocityX, velocityY, velocityZ, spriteProvider.getSprite(random)); + return new TestParticle(world, x, y, z, velocityX, velocityY, velocityZ); } } private static class TestParticle extends Particle { - private final Sprite sprite; - - TestParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, Sprite sprite) { + TestParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) { super(world, x, y, z, velocityX, velocityY, velocityZ); - this.sprite = sprite; } @Override