diff --git a/changelog.md b/changelog.md index 398bd8a1..8983bffb 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,8 @@ +------------------------------------------------------ +Effective 2.4.2 (Alpha) - 1.21.1 +------------------------------------------------------ +- Rewrote ripples and glow ripples + ------------------------------------------------------ Effective 2.4.1 (Alpha) - 1.21.1 ------------------------------------------------------ diff --git a/src/client/java/org/ladysnake/effective/core/Effective.java b/src/client/java/org/ladysnake/effective/core/Effective.java index 9c0ee853..942bb1ed 100644 --- a/src/client/java/org/ladysnake/effective/core/Effective.java +++ b/src/client/java/org/ladysnake/effective/core/Effective.java @@ -107,11 +107,6 @@ public void onInitializeClient() { EffectiveParticles.initialize(); // Particles -// WATERFALL_CLOUD = Registry.register(Registries.PARTICLE_TYPE, Effective.id("waterfall_cloud"), WATERFALL_CLOUD); -// ParticleFactoryRegistry.getInstance().register(WATERFALL_CLOUD, WaterfallCloudParticle.Factory::new); -// MIST = Registry.register(Registries.PARTICLE_TYPE, Effective.id("mist"), MIST); -// ParticleFactoryRegistry.getInstance().register(MIST, MistParticleType.Factory::new); - CHORUS_PETAL = Registry.register(Registries.PARTICLE_TYPE, Effective.id("chorus_petal"), FabricParticleTypes.simple(true)); ParticleFactoryRegistry.getInstance().register(CHORUS_PETAL, ChorusPetalParticle.Factory::new); EYES = Registry.register(Registries.PARTICLE_TYPE, Effective.id("eyes"), FabricParticleTypes.simple(true)); diff --git a/src/client/java/org/ladysnake/effective/core/index/EffectiveParticles.java b/src/client/java/org/ladysnake/effective/core/index/EffectiveParticles.java index 27965a3e..cdc597b9 100644 --- a/src/client/java/org/ladysnake/effective/core/index/EffectiveParticles.java +++ b/src/client/java/org/ladysnake/effective/core/index/EffectiveParticles.java @@ -26,6 +26,8 @@ public interface EffectiveParticles { SimpleParticleType GLOW_RIPPLE = create("glow_ripple", FabricParticleTypes.simple(true)); SimpleParticleType BUBBLE = create("bubble", FabricParticleTypes.simple(true)); SimpleParticleType END_BUBBLE = create("end_bubble", FabricParticleTypes.simple(true)); + SimpleParticleType WATERFALL_CLOUD = create("waterfall_cloud", FabricParticleTypes.simple(true)); + SimpleParticleType MIST = create("mist", FabricParticleTypes.simple(true)); static void initialize() { PARTICLES.keySet().forEach(particle -> Registry.register(Registries.PARTICLE_TYPE, PARTICLES.get(particle), particle)); @@ -47,5 +49,7 @@ private static void registerFactories() { ParticleFactoryRegistry.getInstance().register(GLOW_RIPPLE, GlowRippleParticle.Factory::new); ParticleFactoryRegistry.getInstance().register(BUBBLE, BubbleParticle.Factory::new); ParticleFactoryRegistry.getInstance().register(END_BUBBLE, EndBubbleParticle.Factory::new); + ParticleFactoryRegistry.getInstance().register(WATERFALL_CLOUD, CascadeParticle.Factory::new); + ParticleFactoryRegistry.getInstance().register(MIST, MistParticle.Factory::new); } } diff --git a/src/client/java/org/ladysnake/effective/core/particle/WaterfallCloudParticle.java b/src/client/java/org/ladysnake/effective/core/particle/CascadeParticle.java similarity index 68% rename from src/client/java/org/ladysnake/effective/core/particle/WaterfallCloudParticle.java rename to src/client/java/org/ladysnake/effective/core/particle/CascadeParticle.java index 1b40bb30..9ed3f254 100644 --- a/src/client/java/org/ladysnake/effective/core/particle/WaterfallCloudParticle.java +++ b/src/client/java/org/ladysnake/effective/core/particle/CascadeParticle.java @@ -7,11 +7,12 @@ import net.minecraft.client.world.ClientWorld; import net.minecraft.particle.SimpleParticleType; import net.minecraft.util.math.BlockPos; +import org.ladysnake.effective.core.Effective; -public class WaterfallCloudParticle extends SpriteBillboardParticle { +public class CascadeParticle extends SpriteBillboardParticle { private final SpriteProvider spriteProvider; - public WaterfallCloudParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, SpriteProvider spriteProvider) { + public CascadeParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, SpriteProvider spriteProvider) { super(world, x, y, z, velocityX, velocityY, velocityZ); this.velocityX = velocityX; @@ -19,10 +20,16 @@ public WaterfallCloudParticle(ClientWorld world, double x, double y, double z, d this.velocityZ = velocityZ; this.spriteProvider = spriteProvider; - this.maxAge = 500; - this.scale = .05f; + this.maxAge = 10; + this.scale = .5f; this.setSpriteForAge(spriteProvider); + +// WorldParticleBuilder.create(Effective.WATERFALL_CLOUD) +// .enableForcedSpawn() +// .enableNoClip() +// .setMotion((world.getRandom().nextFloat() * waterfall.strength()) / 10f * Math.signum(offsetX), (world.getRandom().nextFloat() * waterfall.strength()) / 10f, (world.getRandom().nextFloat() * waterfall.strength()) / 10f * Math.signum(offsetZ)) +// .spawn(world, blockPos.getX() + .5 + offsetX, blockPos.getY() + world.getRandom().nextFloat(), blockPos.getZ() + .5 + offsetZ); } public ParticleTextureSheet getType() { @@ -68,7 +75,7 @@ public Factory(SpriteProvider spriteProvider) { @Override public Particle createParticle(SimpleParticleType parameters, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) { - return new WaterfallCloudParticle(world, x, y, z, velocityX, velocityY, velocityZ, this.spriteProvider); + return new CascadeParticle(world, x, y, z, velocityX, velocityY, velocityZ, this.spriteProvider); } } } diff --git a/src/client/java/org/ladysnake/effective/core/particle/GlowRippleParticle.java b/src/client/java/org/ladysnake/effective/core/particle/GlowRippleParticle.java index 6634b6eb..97c1d484 100644 --- a/src/client/java/org/ladysnake/effective/core/particle/GlowRippleParticle.java +++ b/src/client/java/org/ladysnake/effective/core/particle/GlowRippleParticle.java @@ -18,57 +18,22 @@ import org.joml.Vector3f; public class GlowRippleParticle extends RippleParticle { - public float redAndGreen = random.nextFloat() / 5f; - public float blue = 1.0f; public BlockPos pos; private GlowRippleParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, SpriteProvider spriteProvider) { super(world, x, y, z, velocityX, velocityY, velocityZ, spriteProvider); pos = BlockPos.ofFloored(x, y, z); + float randFloat = random.nextFloat() / 5f; + float redAndGreenRender = Math.min(1, randFloat + world.getLightLevel(LightType.BLOCK, pos) / 15f); + this.red = redAndGreenRender; + this.green = redAndGreenRender; + this.blue = 1.0f; } @Override - public void buildGeometry(VertexConsumer vertexConsumer, Camera camera, float tickDelta) { - this.setSpriteForAge(spriteProvider); - - Vec3d vec3d = camera.getPos(); - float f = (float) (MathHelper.lerp(tickDelta, this.prevPosX, this.x) - vec3d.getX()); - float g = (float) (MathHelper.lerp(tickDelta, this.prevPosY, this.y) - vec3d.getY()); - float h = (float) (MathHelper.lerp(tickDelta, this.prevPosZ, this.z) - vec3d.getZ()); - Quaternionf quaternion2; - if (this.angle == 0.0F) { - quaternion2 = camera.getRotation(); - } else { - quaternion2 = new Quaternionf(camera.getRotation()); - float i = MathHelper.lerp(tickDelta, this.prevAngle, this.angle); - quaternion2.rotateZ(i); - } - - Vector3f Vec3f = new Vector3f(-1.0F, -1.0F, 0.0F); - Vec3f.rotate(quaternion2); - Vector3f[] Vec3fs = new Vector3f[]{new Vector3f(-1.0F, -1.0F, 0.0F), new Vector3f(-1.0F, 1.0F, 0.0F), new Vector3f(1.0F, 1.0F, 0.0F), new Vector3f(1.0F, -1.0F, 0.0F)}; - float j = this.getSize(tickDelta); - - for (int k = 0; k < 4; ++k) { - Vector3f Vec3f2 = Vec3fs[k]; - Vec3f2.rotate(new Quaternionf().rotateXYZ((float) Math.toRadians(90f), 0f, 0f)); - Vec3f2.mul(j); - Vec3f2.add(f, g, h); - } - - float minU = this.getMinU(); - float maxU = this.getMaxU(); - float minV = this.getMinV(); - float maxV = this.getMaxV(); - - int l = LightmapTextureManager.MAX_LIGHT_COORDINATE; - float redAndGreenRender = Math.min(1, redAndGreen + world.getLightLevel(LightType.BLOCK, pos) / 15f); - - vertexConsumer.vertex(Vec3fs[0].x(), Vec3fs[0].y(), Vec3fs[0].z()).texture(maxU, maxV).color(redAndGreenRender, redAndGreenRender, blue, alpha).light(l); - vertexConsumer.vertex(Vec3fs[1].x(), Vec3fs[1].y(), Vec3fs[1].z()).texture(maxU, minV).color(redAndGreenRender, redAndGreenRender, blue, alpha).light(l); - vertexConsumer.vertex(Vec3fs[2].x(), Vec3fs[2].y(), Vec3fs[2].z()).texture(minU, minV).color(redAndGreenRender, redAndGreenRender, blue, alpha).light(l); - vertexConsumer.vertex(Vec3fs[3].x(), Vec3fs[3].y(), Vec3fs[3].z()).texture(minU, maxV).color(redAndGreenRender, redAndGreenRender, blue, alpha).light(l); + protected int getBrightness(float tint) { + return LightmapTextureManager.MAX_LIGHT_COORDINATE; } @Environment(EnvType.CLIENT) diff --git a/src/client/java/org/ladysnake/effective/core/particle/MistParticle.java b/src/client/java/org/ladysnake/effective/core/particle/MistParticle.java index b25f584d..45f37455 100644 --- a/src/client/java/org/ladysnake/effective/core/particle/MistParticle.java +++ b/src/client/java/org/ladysnake/effective/core/particle/MistParticle.java @@ -2,16 +2,38 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleFactory; -import net.minecraft.client.particle.ParticleTextureSheet; -import net.minecraft.client.particle.SpriteBillboardParticle; +import net.minecraft.client.particle.*; import net.minecraft.client.world.ClientWorld; import net.minecraft.particle.SimpleParticleType; +import org.ladysnake.effective.core.Effective; public class MistParticle extends SpriteBillboardParticle { - protected MistParticle(ClientWorld clientWorld, double d, double e, double f) { - super(clientWorld, d, e, f); + public MistParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, SpriteProvider spriteProvider) { + super(world, x, y, z, velocityX, velocityY, velocityZ); + + this.velocityX = velocityX; + this.velocityY = velocityY; + this.velocityZ = velocityZ; + + this.setSpriteForAge(spriteProvider); + + +// WorldParticleBuilder.create(Effective.MIST) +// .enableForcedSpawn() +// .setSpinData(SpinParticleData.create((world.random.nextFloat() - world.random.nextFloat()) / 20f).build()) +// .setScaleData(GenericParticleData.create(10f + world.random.nextFloat() * 5f).build()) +// .setTransparencyData( +// GenericParticleData.create(0.001f, 0.1f, 0f) +// .setEasing(Easing.EXPO_OUT, Easing.SINE_OUT) +// .build() +// ) +// .setLifetime(300) +// .enableNoClip() +// .setNaturalLighting() +// .setRenderType(LodestoneWorldParticleRenderType.TRANSPARENT.withDepthFade()) +// .setColorData(ColorParticleData.create(waterfall.mistColor(), waterfall.mistColor()).build()) +// .setMotion(world.getRandom().nextFloat() / 15f * Math.signum(offsetX), world.getRandom().nextGaussian() / 25f, world.getRandom().nextFloat() / 15f * Math.signum(offsetZ)) +// .spawn(world, blockPos.getX() + .5f, blockPos.getY() + .5f, blockPos.getZ() + .5f); } @Override @@ -21,9 +43,15 @@ public ParticleTextureSheet getType() { @Environment(EnvType.CLIENT) public static class Factory implements ParticleFactory { + private final SpriteProvider spriteProvider; + + public Factory(SpriteProvider spriteProvider) { + this.spriteProvider = spriteProvider; + } + @Override public Particle createParticle(SimpleParticleType parameters, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) { - return new MistParticle(world, x, y, z); + return new MistParticle(world, x, y, z, velocityX, velocityY, velocityZ, this.spriteProvider); } } } diff --git a/src/client/java/org/ladysnake/effective/core/render/particle/SoftParticleRenderType.java b/src/client/java/org/ladysnake/effective/core/render/particle/SoftParticleRenderType.java new file mode 100644 index 00000000..6f336c83 --- /dev/null +++ b/src/client/java/org/ladysnake/effective/core/render/particle/SoftParticleRenderType.java @@ -0,0 +1,38 @@ +//package org.ladysnake.effective.core.render.particle; +// +//import com.mojang.blaze3d.systems.RenderSystem; +//import net.minecraft.client.MinecraftClient; +//import net.minecraft.client.particle.ParticleTextureSheet; +//import net.minecraft.client.render.BufferBuilder; +//import net.minecraft.client.render.Tessellator; +//import net.minecraft.client.texture.SpriteAtlasTexture; +//import net.minecraft.client.texture.TextureManager; +//import org.jetbrains.annotations.NotNull; +//import org.jetbrains.annotations.Nullable; +// +//public class SoftParticleRenderType implements ParticleTextureSheet { +// @NotNull +// public static final SoftParticleRenderType SOFT_PARTICLE = new SoftParticleRenderType(); +// +// @Override +// public @Nullable BufferBuilder begin(Tessellator tessellator, TextureManager textureManager) { +// final MinecraftClient minecraft = MinecraftClient.getInstance(); +// +// RenderSystem.setShader(() -> softParticle); +// +// // Disallow soft particles from writing to the depth buffer +// RenderSystem.depthMask(false); +// +// // Set `Sampler0` to the particle atlas +// // noinspection deprecation +// RenderSystem.setShaderTexture(0, SpriteAtlasTexture.PARTICLE_ATLAS_TEXTURE); +// +// RenderSystem.enableBlend(); +// RenderSystem.defaultBlendFunc(); +// +// // Set the sampler for the depth texture +// softParticle.setSampler("DiffuseDepthSampler", minecraft.getMainRenderTarget().getDepthTextureId()); +// +// return tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.PARTICLE); +// } +//} diff --git a/src/client/java/org/ladysnake/effective/core/world/WaterfallCloudGenerators.java b/src/client/java/org/ladysnake/effective/core/world/WaterfallCloudGenerators.java index 53722432..0071ba6d 100644 --- a/src/client/java/org/ladysnake/effective/core/world/WaterfallCloudGenerators.java +++ b/src/client/java/org/ladysnake/effective/core/world/WaterfallCloudGenerators.java @@ -148,53 +148,26 @@ private static Waterfall getWaterfallAt(BlockView world, BlockPos pos, FluidStat } public static void addWaterfallCloud(World world, Waterfall waterfall) { -// boolean isGlowingWater = EffectiveUtils.isGlowingWater(world, waterfall.blockPos()); -// Color glowingWaterColor = EffectiveUtils.getGlowingWaterColor(world, waterfall.blockPos()); -// Color white = new Color(0xFFFFFF); -// BlockPos blockPos = waterfall.blockPos(); -// -// for (int i = 0; i < EffectiveConfig.cascadeCloudDensity; i++) { -// if (waterfall != null) { -// double offsetX = world.getRandom().nextGaussian() / 5f; -// double offsetZ = world.getRandom().nextGaussian() / 5f; -// -// WorldParticleBuilder.create(Effective.WATERFALL_CLOUD) -// .enableForcedSpawn() -// .enableNoClip() -// .setLightLevel(isGlowingWater ? LightmapTextureManager.MAX_LIGHT_COORDINATE : -1) -// .setScaleData(GenericParticleData.create((0.4f + waterfall.strength() * world.random.nextFloat())).build()) -// .setColorData(ColorParticleData.create(isGlowingWater ? glowingWaterColor : white, isGlowingWater ? glowingWaterColor : white).build()) -// .setLifetime(10) -// .setRenderType(LodestoneWorldParticleRenderType.TRANSPARENT.withDepthFade()) -// .setMotion((world.getRandom().nextFloat() * waterfall.strength()) / 10f * Math.signum(offsetX), (world.getRandom().nextFloat() * waterfall.strength()) / 10f, (world.getRandom().nextFloat() * waterfall.strength()) / 10f * Math.signum(offsetZ)) -// .spawn(world, blockPos.getX() + .5 + offsetX, blockPos.getY() + world.getRandom().nextFloat(), blockPos.getZ() + .5 + offsetZ); -// } -// } -// -// if (EffectiveConfig.cascadeMistDensity > 0f && waterfall.strength() >= 1.6f) { -// if ((world.random.nextFloat() * 100f) <= EffectiveConfig.cascadeMistDensity) { -// double offsetX = world.getRandom().nextGaussian() / 5f; -// double offsetZ = world.getRandom().nextGaussian() / 5f; -// -// WorldParticleBuilder.create(Effective.MIST) -// .enableForcedSpawn() -// .setSpinData(SpinParticleData.create((world.random.nextFloat() - world.random.nextFloat()) / 20f).build()) -// .setScaleData(GenericParticleData.create(10f + world.random.nextFloat() * 5f).build()) -// .setTransparencyData( -// GenericParticleData.create(0.001f, 0.1f, 0f) -// .setEasing(Easing.EXPO_OUT, Easing.SINE_OUT) -// .build() -// ) -// .setLifetime(300) -// .enableNoClip() -// .setNaturalLighting() -// .setRenderType(LodestoneWorldParticleRenderType.TRANSPARENT.withDepthFade()) -// .setColorData(ColorParticleData.create(waterfall.mistColor(), waterfall.mistColor()).build()) -// .setMotion(world.getRandom().nextFloat() / 15f * Math.signum(offsetX), world.getRandom().nextGaussian() / 25f, world.getRandom().nextFloat() / 15f * Math.signum(offsetZ)) -// .spawn(world, blockPos.getX() + .5f, blockPos.getY() + .5f, blockPos.getZ() + .5f); -// } -// } + boolean isGlowingWater = EffectiveUtils.isGlowingWater(world, waterfall.blockPos()); + Color glowingWaterColor = EffectiveUtils.getGlowingWaterColor(world, waterfall.blockPos()); + Color white = new Color(0xFFFFFF); + BlockPos blockPos = waterfall.blockPos(); + for (int i = 0; i < EffectiveConfig.cascadeCloudDensity; i++) { + if (waterfall != null) { + double offsetX = world.getRandom().nextGaussian() / 5f; + double offsetZ = world.getRandom().nextGaussian() / 5f; + + } + } + + if (EffectiveConfig.cascadeMistDensity > 0f && waterfall.strength() >= 1.6f) { + if ((world.random.nextFloat() * 100f) <= EffectiveConfig.cascadeMistDensity) { + double offsetX = world.getRandom().nextGaussian() / 5f; + double offsetZ = world.getRandom().nextGaussian() / 5f; + + } + } } public static void scheduleParticleTick(Waterfall waterfall, int ticks) { diff --git a/src/client/resources/assets/effective/shaders/core/soft_particle.fsh b/src/client/resources/assets/effective/shaders/core/soft_particle.fsh new file mode 100644 index 00000000..b83f8d9d --- /dev/null +++ b/src/client/resources/assets/effective/shaders/core/soft_particle.fsh @@ -0,0 +1,45 @@ +#version 150 + +#moj_import + +uniform sampler2D Sampler0; +uniform sampler2D Sampler2; +uniform sampler2D DiffuseDepthSampler; + +uniform mat4 ProjMat; +uniform vec4 ColorModulator; +uniform float FogStart; +uniform float FogEnd; +uniform vec4 FogColor; +uniform vec2 ScreenSize; + +in float vertexDistance; +in vec2 texCoord0; +in vec4 vertexColor; + +out vec4 fragColor; + +const vec3 normal = vec3(0.0, 0.0, 1.0); + +float linearizeDepth(float depthSample) { + // Same calculation mojang does, to linearize depths using the projection matrix values + return -ProjMat[3].z / (depthSample * -2.0 + 1.0 - ProjMat[2].z); +} + +void main() { + vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; + if (color.a < 0.001) { + discard; + } + + // Depth only occupies the red channel, we don't care about the other two + float depthSample = texture(DiffuseDepthSampler, gl_FragCoord.xy / ScreenSize).r; + + float depth = linearizeDepth(depthSample); + float particleDepth = linearizeDepth(gl_FragCoord.z); + + // Linearly blends from 1x to 0x opacity at 1+ meter depth difference to 0 depth difference + float opacity = color.a * min(depth - particleDepth, 1.0); + + fragColor = linear_fog(vec4(color.rgb, opacity), vertexDistance, FogStart, FogEnd, FogColor); +} diff --git a/src/client/resources/assets/effective/shaders/core/soft_particle.json b/src/client/resources/assets/effective/shaders/core/soft_particle.json new file mode 100644 index 00000000..16e0e2a0 --- /dev/null +++ b/src/client/resources/assets/effective/shaders/core/soft_particle.json @@ -0,0 +1,19 @@ +{ + "vertex": "particle", + "fragment": "effective:soft_particle", + "samplers": [ + { "name": "Sampler0" }, + { "name": "Sampler2" }, + { "name": "DiffuseDepthSampler" } + ], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, + { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, + { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, + { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] }, + { "name": "ScreenSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] } + ] +} diff --git a/src/client/resources/effective.accesswidener b/src/client/resources/effective.accesswidener index b1d23a81..fec1c002 100644 --- a/src/client/resources/effective.accesswidener +++ b/src/client/resources/effective.accesswidener @@ -9,3 +9,4 @@ accessible field net/minecraft/block/entity/EnderChestBlockEntity lidAnimator Ln accessible field net/minecraft/block/entity/EnderChestBlockEntity stateManager Lnet/minecraft/block/entity/ViewerCountManager; accessible field net/minecraft/client/sound/SoundManager soundSystem Lnet/minecraft/client/sound/SoundSystem; accessible field net/minecraft/client/sound/SoundSystem tickingSounds Ljava/util/List; +accessible field net/minecraft/client/render/GameRenderer programs Ljava/util/Map;