From 2754d41ee9df544cedea3a5e82ce4d08975be9d3 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 13 Feb 2024 15:35:26 +0000 Subject: [PATCH] Fix dust appearing in the ground and fix clouds appearing black (use per-vertex lighting) --- .../particle/AbstractBillboardParticle.java | 1 + .../client/particle/DustCloudParticle.java | 45 +++++++++++-------- .../client/render/model/BakedModel.java | 8 +++- .../client/render/model/FanModel.java | 40 +++++++++++++++++ .../render/model/VertexLightSource.java | 44 ++++++++++++++++++ .../client/render/shader/UShaders.java | 13 ++---- .../render/spell/PortalFrameBuffer.java | 4 +- .../unicopia/entity/player/PlayerPhysics.java | 2 +- 8 files changed, 124 insertions(+), 33 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/client/render/model/FanModel.java create mode 100644 src/main/java/com/minelittlepony/unicopia/client/render/model/VertexLightSource.java diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractBillboardParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractBillboardParticle.java index 02d624c6..52420762 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractBillboardParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractBillboardParticle.java @@ -27,6 +27,7 @@ public abstract class AbstractBillboardParticle extends AbstractGeometryBasedPar RenderSystem.disableCull(); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); + RenderSystem.defaultBlendFunc(); Vec3d cam = camera.getPos(); diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/DustCloudParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/DustCloudParticle.java index e39bb0b0..2e550c7a 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/DustCloudParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/DustCloudParticle.java @@ -1,11 +1,16 @@ package com.minelittlepony.unicopia.client.particle; +import org.joml.Vector4f; + import com.minelittlepony.common.util.Color; -import com.minelittlepony.unicopia.client.render.RenderUtil; +import com.minelittlepony.unicopia.client.render.model.FanModel; +import com.minelittlepony.unicopia.client.render.model.VertexLightSource; import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormat; +import net.minecraft.client.render.VertexFormats; import net.minecraft.client.texture.Sprite; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; @@ -16,15 +21,15 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RotationAxis; public class DustCloudParticle extends AbstractBillboardParticle { - //private static final Identifier TEXTURE = new Identifier("textures/particle/big_smoke_3.png"); - protected static final int SEGMENTS = 20; protected static final int SEPARATION = 270 / SEGMENTS; private float scaleFactor; protected Sprite sprite; - private final RenderUtil.Vertex[] vertices; + private final FanModel model; + + private final VertexLightSource lightSource; public DustCloudParticle(BlockStateParticleEffect effect, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) { super(world, x, y, z, velocityX, velocityY, velocityZ); @@ -33,14 +38,15 @@ public class DustCloudParticle extends AbstractBillboardParticle { red = 0.6F; green = 0.6F; blue = 0.6F; - alpha = (float)world.getRandom().nextTriangular(0.6, 0.2); + alpha = (float)world.getRandom().nextTriangular(0.6, 0.2) * 0.3F; scaleFactor = (float)world.getRandom().nextTriangular(2, 1.2); sprite = MinecraftClient.getInstance().getBlockRenderManager().getModels().getModelParticleSprite(effect.getBlockState()); - vertices = new RenderUtil.Vertex[]{ - new RenderUtil.Vertex(-1, -1, 0, sprite.getMinU(), sprite.getMinV()), - new RenderUtil.Vertex(-1, 1, 0, sprite.getMaxU(), sprite.getMinV()), - new RenderUtil.Vertex( 1, 1, 0, sprite.getMaxU(), sprite.getMaxV()), - new RenderUtil.Vertex( 1, -1, 0, sprite.getMinU(), sprite.getMaxV()) + lightSource = new VertexLightSource(world); + model = new FanModel(sprite) { + @Override + protected int getLightAt(Vector4f pos, int light) { + return lightSource.getLight(pos, light); + } }; if (!effect.getBlockState().isOf(Blocks.GRASS_BLOCK)) { int i = MinecraftClient.getInstance().getBlockColors().getColor(effect.getBlockState(), world, BlockPos.ofFloored(x, y, z), 0); @@ -60,26 +66,29 @@ public class DustCloudParticle extends AbstractBillboardParticle { super.tick(); scaleFactor += 0.001F; scale(MathHelper.clamp(age / 5F, 0, 1) * scaleFactor); + lightSource.tick(); } @Override protected void renderQuads(Tessellator te, BufferBuilder buffer, float x, float y, float z, float tickDelta) { - float scale = getScale(tickDelta); + float scale = getScale(tickDelta) * 0.5F; float alpha = this.alpha * (1 - ((float)age / maxAge)); MatrixStack matrices = new MatrixStack(); matrices.translate(x, y, z); - matrices.scale(scale, scale * 0.5F, scale); + matrices.scale(1, 0.5F, 1); - float angle = ((this.age + tickDelta) % 360) / SEGMENTS; + float angle = (MathHelper.sin((this.age + tickDelta) / 100F) * 360) / SEGMENTS; for (int i = 0; i < SEGMENTS; i++) { matrices.push(); - matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees((i * angle) % 360)); - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees((SEPARATION * i + angle) % 360)); - matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees((SEPARATION * i + angle) % 360)); + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees((i * angle))); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees((SEPARATION * i - angle))); + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees((SEPARATION * i + angle))); float ringScale = 1 + MathHelper.sin(((i * 10) + age + tickDelta) * 0.05F) * 0.1F; - matrices.scale(ringScale, ringScale, ringScale); - renderQuad(matrices, te, buffer, vertices, alpha, tickDelta); + + buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT); + model.render(matrices, buffer, 0, scale * ringScale, 1, 1, 1, alpha); + te.draw(); matrices.pop(); } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/model/BakedModel.java b/src/main/java/com/minelittlepony/unicopia/client/render/model/BakedModel.java index 3bceca54..58e65456 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/model/BakedModel.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/model/BakedModel.java @@ -50,7 +50,7 @@ public class BakedModel { textureMatrix.identity(); } - public final void render(MatrixStack matrices, VertexConsumer buffer, float scale, float r, float g, float b, float a) { + public final void render(MatrixStack matrices, VertexConsumer buffer, int light, float scale, float r, float g, float b, float a) { scale = Math.abs(scale); if (scale < 0.001F) { return; @@ -62,9 +62,13 @@ public class BakedModel { for (RenderUtil.Vertex vertex : vertices) { Vector4f pos = vertex.position(positionmatrix); Vector4f tex = vertex.texture(textureMatrix); - buffer.vertex(pos.x, pos.y, pos.z).texture(tex.x, tex.y).color(r, g, b, a).next(); + buffer.vertex(pos.x, pos.y, pos.z).texture(tex.x, tex.y).color(r, g, b, a).light(getLightAt(pos, light)).next(); } matrices.pop(); textureMatrix.identity(); } + + protected int getLightAt(Vector4f pos, int light) { + return light; + } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/model/FanModel.java b/src/main/java/com/minelittlepony/unicopia/client/render/model/FanModel.java new file mode 100644 index 00000000..29eaf2d2 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/render/model/FanModel.java @@ -0,0 +1,40 @@ +package com.minelittlepony.unicopia.client.render.model; + +import com.minelittlepony.unicopia.client.render.RenderUtil; + +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.RotationAxis; + +public class FanModel extends BakedModel { + + public FanModel(Sprite sprite) { + RenderUtil.Vertex[] dorito = createDorito(sprite); + MatrixStack matrices = new MatrixStack(); + for (int d = 0; d < 12; d++) { + matrices.push(); + + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(30 * d)); + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(15)); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(15 * d)); + matrices.translate(2.9F, 0, 0); + for (RenderUtil.Vertex corner : dorito) { + var position = corner.position(matrices.peek().getPositionMatrix()); + addVertex(position.x, position.y(), position.z(), corner.texture().x, corner.texture().y); + } + matrices.pop(); + } + } + + static RenderUtil.Vertex[] createDorito(Sprite sprite) { + float chunkSize = 1F; + float baseLength = 0.8F; + float uLength = sprite.getMaxU() - sprite.getMinU(); + return new RenderUtil.Vertex[]{ + new RenderUtil.Vertex(-chunkSize, -chunkSize * baseLength, 0, sprite.getMinU() + uLength * baseLength, sprite.getMinV()), + new RenderUtil.Vertex( chunkSize, 0, 0, sprite.getMaxU(), sprite.getMaxV()), + new RenderUtil.Vertex(-chunkSize, chunkSize * baseLength, 0, sprite.getMinU(), sprite.getMinV()), + new RenderUtil.Vertex(-chunkSize * 3, 0, 0, sprite.getMinU(), sprite.getMaxV()) + }; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/model/VertexLightSource.java b/src/main/java/com/minelittlepony/unicopia/client/render/model/VertexLightSource.java new file mode 100644 index 00000000..86184540 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/render/model/VertexLightSource.java @@ -0,0 +1,44 @@ +package com.minelittlepony.unicopia.client.render.model; + +import org.joml.Vector4f; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; + +public class VertexLightSource { + private final ClientWorld world; + private final Long2ObjectMap lightCache = new Long2ObjectOpenHashMap<>(); + + public VertexLightSource(ClientWorld world) { + this.world = world; + } + + public void tick() { + lightCache.clear(); + } + + public int getLight(Vector4f vertexPosition, int light) { + return lightCache.computeIfAbsent(getBlockPosition(vertexPosition), this::getLight); + } + + @SuppressWarnings("deprecation") + private int getLight(long p) { + final BlockPos pos = BlockPos.fromLong(p); + return world.isChunkLoaded(pos) ? WorldRenderer.getLightmapCoordinates(world, pos) : 0; + } + + private long getBlockPosition(Vector4f vertexPosition) { + Vec3d cameraPos = MinecraftClient.getInstance().gameRenderer.getCamera().getPos(); + return BlockPos.asLong( + MathHelper.floor(cameraPos.x + vertexPosition.x), + MathHelper.floor(cameraPos.y + vertexPosition.y), + MathHelper.floor(cameraPos.z + vertexPosition.z) + ); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/shader/UShaders.java b/src/main/java/com/minelittlepony/unicopia/client/render/shader/UShaders.java index fd86786d..9a7d3cc7 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/shader/UShaders.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/shader/UShaders.java @@ -3,23 +3,16 @@ package com.minelittlepony.unicopia.client.render.shader; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; -import org.jetbrains.annotations.Nullable; - import com.minelittlepony.unicopia.Unicopia; import net.fabricmc.fabric.api.client.rendering.v1.CoreShaderRegistrationCallback; import net.minecraft.client.gl.ShaderProgram; import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormats; -public final class UShaders { - @Nullable - private static Supplier renderTypePortalSurfaceProgram = register("rendertype_portal_surface", VertexFormats.POSITION_COLOR); +public interface UShaders { + Supplier RENDER_TYPE_PORTAL_SURFACE = register("rendertype_portal_surface", VertexFormats.POSITION_COLOR); - public static ShaderProgram getRenderTypePortalSurfaceProgram() { - return renderTypePortalSurfaceProgram.get(); - } - - public static void bootstrap() { } + static void bootstrap() { } static Supplier register(String name, VertexFormat format) { AtomicReference holder = new AtomicReference<>(); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalFrameBuffer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalFrameBuffer.java index 823220f5..e594b647 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalFrameBuffer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalFrameBuffer.java @@ -94,14 +94,14 @@ class PortalFrameBuffer implements AutoCloseable { BufferBuilder buffer = tessellator.getBuffer(); float uScale = (float)framebuffer.viewportWidth / (float)framebuffer.textureWidth; float vScale = (float)framebuffer.viewportHeight / (float)framebuffer.textureHeight; - RenderSystem.setShader(UShaders::getRenderTypePortalSurfaceProgram); + RenderSystem.setShader(UShaders.RENDER_TYPE_PORTAL_SURFACE); //RenderSystem.setShader(GameRenderer::getPositionTexColorProgram); RenderSystem._setShaderTexture(0, framebuffer.getColorAttachment()); buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR); SphereModel.DISK.scaleUV(uScale, vScale); RenderSystem.setTextureMatrix(SphereModel.DISK.getTextureMatrix()); - SphereModel.DISK.render(matrices, buffer, 2F, 1, 1, 1, 1); + SphereModel.DISK.render(matrices, buffer, 1, 2F, 1, 1, 1, 1); tessellator.draw(); client.getTextureManager().bindTexture(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java index e1a6cd75..971f8b26 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -567,7 +567,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab if (entity.isOnGround() || !force) { BlockState steppingState = pony.asEntity().getSteppingBlockState(); if (steppingState.isIn(UTags.KICKS_UP_DUST)) { - pony.addParticle(new BlockStateParticleEffect(UParticles.DUST_CLOUD, steppingState), pony.getOrigin().down().toCenterPos(), Vec3d.ZERO); + pony.addParticle(new BlockStateParticleEffect(UParticles.DUST_CLOUD, steppingState), pony.getOrigin().toCenterPos(), Vec3d.ZERO); } else { Supplier pos = VecHelper.sphere(pony.asWorld().getRandom(), 0.5D); Supplier vel = VecHelper.sphere(pony.asWorld().getRandom(), 0.015D);