diff --git a/common/src/main/java/com/seibel/lod/common/Config.java b/common/src/main/java/com/seibel/lod/common/Config.java index 3d3c7f6bc..a2f8639c5 100644 --- a/common/src/main/java/com/seibel/lod/common/Config.java +++ b/common/src/main/java/com/seibel/lod/common/Config.java @@ -83,6 +83,10 @@ public class Config extends ConfigGui @ConfigAnnotations.ScreenEntry public static FogQuality fogQuality; + @ConfigAnnotations.Category("client.graphics") + @ConfigAnnotations.ScreenEntry + public static CloudQuality cloudQuality; + @ConfigAnnotations.Category("client.graphics") @ConfigAnnotations.ScreenEntry public static AdvancedGraphics advancedGraphics; @@ -132,6 +136,18 @@ public class Config extends ConfigGui } + public static class CloudQuality + { + @ConfigAnnotations.Category("client.graphics.cloudQuality") + @ConfigAnnotations.Entry + public static boolean extendClouds = true; + + @ConfigAnnotations.Category("client.graphics.cloudQuality") + @ConfigAnnotations.Entry + public static int cloudHeight = 192; + } + + public static class AdvancedGraphics { @@ -142,7 +158,7 @@ public class Config extends ConfigGui @ConfigAnnotations.Category("client.graphics.advancedGraphics") @ConfigAnnotations.Entry public static boolean alwaysDrawAtMaxQuality = IAdvancedGraphics.ALWAYS_DRAW_AT_MAD_QUALITY_DEFAULT; - + @ConfigAnnotations.Category("client.graphics.advancedGraphics") @ConfigAnnotations.Entry public static VanillaOverdraw vanillaOverdraw = IAdvancedGraphics.VANILLA_OVERDRAW_DEFAULT; diff --git a/common/src/main/java/com/seibel/lod/common/clouds/CloudTexture.java b/common/src/main/java/com/seibel/lod/common/clouds/CloudTexture.java new file mode 100644 index 000000000..0da3f309e --- /dev/null +++ b/common/src/main/java/com/seibel/lod/common/clouds/CloudTexture.java @@ -0,0 +1,92 @@ +package com.seibel.lod.common.clouds; + +import com.mojang.blaze3d.platform.NativeImage; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.levelgen.LegacyRandomSource; +import net.minecraft.world.level.levelgen.synth.SimplexNoise; + +import java.util.*; +import java.util.List; + +public class CloudTexture { + + public List pixels = new LinkedList() {}; + + public SimplexNoise noise; + public DynamicTexture cloudsTexture; + public ResourceLocation resourceLocation; + public double cloudiness; + + public CloudTexture(ResourceLocation resourceLocation) { + this.resourceLocation = resourceLocation; + } + + public void updateImage(long time) { + Random random = new Random(time); + + // Comment to clear sky + SkyCoverGenerators.cloudySkyUpdate(random, this.noise, this.cloudsTexture.getPixels(), pixels, this.cloudiness); + + } + + public void updatePixels() { + pixels.removeIf(pixel -> !fadePixel(Objects.requireNonNull(this.cloudsTexture.getPixels()), pixel.posX, pixel.posZ, pixel.fading)); + + this.cloudsTexture.upload(); + } + + public boolean fadePixel(NativeImage image, int x, int z, boolean fading) { + int color = image.getPixelRGBA(x, z); + int alpha = (color >> 24) & 0xFF; + //int alpha = image.getLuminanceOrAlpha(x, z) + 128; + + if (fading) alpha -= 5; + else alpha += 5; + + int newColor = alpha << 24 | 255 << 16 | 255 << 8 | 255; + //int newColor = NativeImage.combine(alpha, 255, 255, 255); + image.setPixelRGBA(x, z, newColor); + + if (alpha <= 0) { + image.setPixelRGBA(x, z, 0); + return false; + } else return alpha < 255; + } + + public void setTexture(DynamicTexture texture) { + this.cloudsTexture = texture; + } + + public void initNoise(Random random) { +// this.noise = new SimplexNoise(new WorldgenRandom(random.nextLong())); + this.noise = new SimplexNoise(new LegacyRandomSource(random.nextLong())); + } + + public DynamicTexture getNativeImage() { + NativeImage image = new NativeImage(256, 256, false); + + Random random = new Random(); + + this.cloudiness = random.nextDouble(); + + // Switch these out to clear sky + // Never comment both or something weird will happen +// SkyCoverGenerators.clearSkyGenerator(this.noise, image, this.cloudiness); + SkyCoverGenerators.cloudySkyGenerator(this.noise, image, this.cloudiness); + + return new DynamicTexture(image); + } + + public static class PixelCoordinate { + public int posX; + public int posZ; + public boolean fading; + + public PixelCoordinate(int posX, int posZ, boolean fading) { + this.posX = posX; + this.posZ = posZ; + this.fading = fading; + } + } +} diff --git a/common/src/main/java/com/seibel/lod/common/clouds/NoiseCloudHandler.java b/common/src/main/java/com/seibel/lod/common/clouds/NoiseCloudHandler.java new file mode 100644 index 000000000..366373a11 --- /dev/null +++ b/common/src/main/java/com/seibel/lod/common/clouds/NoiseCloudHandler.java @@ -0,0 +1,56 @@ +package com.seibel.lod.common.clouds; + +import net.minecraft.client.Minecraft; +import net.minecraft.resources.ResourceLocation; + +import java.util.LinkedList; +import java.util.List; + +public final class NoiseCloudHandler { + + public static List cloudTextures = new LinkedList() {}; + + private static long cloudIdx = -1; + private static long timeIdx = -1; + private static long lastTime = -1; + + public static void update() { + Minecraft client = Minecraft.getInstance(); + assert client.level != null; + long time = client.level.getGameTime(); + if (time > lastTime) { + lastTime = time; + updateSkyCover(time); + + long update = time / 600; + if (update > timeIdx) { + timeIdx = update; + for (CloudTexture cloudTexture : cloudTextures) { + if (cloudTexture.cloudsTexture.getPixels() != null) { + cloudTexture.updateImage(time); + } + } + } + + for (CloudTexture cloudTexture : cloudTextures) { + if (cloudTexture.cloudsTexture.getPixels() != null) { + cloudTexture.updatePixels(); + } + } + } + } + + public static void updateSkyCover(long time) { + long idx = time / 12000; + + if (idx > cloudIdx) { + cloudIdx = idx; + } + } + + public static void initCloudTextures(ResourceLocation defaultCloud) { + CloudTexture defaultCloudTexture = new CloudTexture(defaultCloud); + + cloudTextures.add(defaultCloudTexture); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/seibel/lod/common/clouds/SkyCoverGenerators.java b/common/src/main/java/com/seibel/lod/common/clouds/SkyCoverGenerators.java new file mode 100644 index 000000000..c56b7b80d --- /dev/null +++ b/common/src/main/java/com/seibel/lod/common/clouds/SkyCoverGenerators.java @@ -0,0 +1,68 @@ +package com.seibel.lod.common.clouds; + +import com.mojang.blaze3d.platform.NativeImage; +import net.minecraft.world.level.levelgen.synth.SimplexNoise; + +import java.util.List; +import java.util.Random; + +public class SkyCoverGenerators { + + public static final int COLOR = NativeImage.combine(255, 255, 255, 255); + + // Where the generator for clouds could be made + // TODO: Try to impliment this https://www.reddit.com/r/Minecraft/comments/e7xol/this_is_how_clouds_should_work_gif_simulation/ + + public static void clearSkyGenerator(SimplexNoise noiseSampler, NativeImage image, double cloudiness) { + for (int x = 0; x < 256; x++) { + for (int z = 0; z < 256; z++) { + if (noiseSampler.getValue(x / 16.0, 0, z / 16.0) * 2.5 < cloudiness || image.getPixelRGBA(x, z) != 0) { + image.setPixelRGBA(x, z, 0); + } + } + } + } + + public static void cloudySkyGenerator(SimplexNoise noiseSampler, NativeImage image, double cloudiness) { + for (int x = 0; x < 256; x++) { + for (int z = 0; z < 256; z++) { + image.setPixelRGBA(x, z, COLOR); + if (noiseSampler.getValue(x / 16.0, 0, z / 16.0) * 2.5 >= cloudiness || image.getPixelRGBA(x, z) != 0) { + if ((int) (noiseSampler.getValue(x / 16.0, 0, z / 16.0) * 2.5) != 0) { + image.setPixelRGBA(x, z, 0); + } + } + } + } + } + + public static void cloudySkyUpdate(Random random, SimplexNoise noiseSampler, NativeImage image, List pixels, double cloudiness) { + int count = random.nextInt(4000) + 4000; + + for (int i = 0; i < count; i++) { + int x = random.nextInt(256); + int z = random.nextInt(256); + + if (!updatingPixel(x, z, pixels)) { + if (noiseSampler.getValue(x / 16.0, 0, z / 16.0) * 2.5 < cloudiness && image.getPixelRGBA(x, z) == 0) { + if ((int) (noiseSampler.getValue(x / 16.0, 0, z / 16.0) * 2.5) != 0) { + pixels.add(new CloudTexture.PixelCoordinate(x, z, true)); + } else { + pixels.add(new CloudTexture.PixelCoordinate(x, z, false)); + } + } else { + pixels.add(new CloudTexture.PixelCoordinate(x, z, false)); + } + } + } + } + + public static boolean updatingPixel(int x, int z, List pixels) { + for (CloudTexture.PixelCoordinate pixel : pixels) { + if (pixel.posX == x && pixel.posZ == z) { + return true; + } + } + return false; + } +} diff --git a/common/src/main/resources/assets/lod/lang/en_us.json b/common/src/main/resources/assets/lod/lang/en_us.json index c2aa81225..878a663cf 100644 --- a/common/src/main/resources/assets/lod/lang/en_us.json +++ b/common/src/main/resources/assets/lod/lang/en_us.json @@ -24,6 +24,9 @@ "DistantHorizons.config.client.graphics.fogQuality.fogColorMode.@tooltip": "What color should fog use?", "DistantHorizons.config.client.graphics.fogQuality.disableVanillaFog": "Disable vanilla fog", "DistantHorizons.config.client.graphics.fogQuality.disableVanillaFog.@tooltip": "If true disable Minecraft's fog. \nMay cause issues with other mods that edit fog. \nMay cause errors with other fog editing mods", + "DistantHorizons.config.client.graphics.cloudQuality": "Cloud options", + "DistantHorizons.config.client.graphics.cloudQuality.extendClouds": "Extend the clouds", + "DistantHorizons.config.client.graphics.cloudQuality.cloudHeight": "Cloud height", "DistantHorizons.config.client.graphics.advancedGraphics": "Advanced quality option", "DistantHorizons.config.client.graphics.advancedGraphics.lodTemplate": "LOD template", "DistantHorizons.config.client.graphics.advancedGraphics.lodTemplate.@tooltip": "How should the LODs be drawn? \nNOTE: Currently only CUBIC is implemented!", diff --git a/fabric/src/main/java/com/seibel/lod/fabric/mixins/MixinWorldRenderer.java b/fabric/src/main/java/com/seibel/lod/fabric/mixins/MixinWorldRenderer.java index b19643642..8787a107c 100644 --- a/fabric/src/main/java/com/seibel/lod/fabric/mixins/MixinWorldRenderer.java +++ b/fabric/src/main/java/com/seibel/lod/fabric/mixins/MixinWorldRenderer.java @@ -21,6 +21,9 @@ package com.seibel.lod.fabric.mixins; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix4f; +import com.seibel.lod.common.Config; +import com.seibel.lod.common.clouds.CloudTexture; +import com.seibel.lod.common.clouds.NoiseCloudHandler; import com.seibel.lod.common.wrappers.McObjectConverter; import net.minecraft.client.renderer.LevelRenderer; import org.spongepowered.asm.mixin.Mixin; @@ -33,6 +36,26 @@ import com.seibel.lod.core.objects.math.Mat4f; import net.minecraft.client.renderer.RenderType; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.*; +import com.mojang.math.Matrix4f; +import net.minecraft.client.CloudStatus; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.network.chat.ChatType; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.*; + +import java.util.Random; + /** * This class is used to mix in my rendering code * before Minecraft starts rendering blocks. @@ -40,21 +63,49 @@ import net.minecraft.client.renderer.RenderType; * render last event, the LODs would render on top * of the normal terrain. * + * This is also the mixin for rendering the clouds + * * @author coolGi2007 * @author James Seibel - * @version 11-21-2021 + * @version 12-31-2021 */ @Mixin(LevelRenderer.class) public class MixinWorldRenderer { + @Final @Shadow private static ResourceLocation CLOUDS_LOCATION; + @Shadow private final int ticks; + @Final @Shadow @NotNull private final Minecraft minecraft; + @Shadow private int prevCloudX; + @Shadow private int prevCloudY; + @Shadow private int prevCloudZ; + @Shadow @NotNull private Vec3 prevCloudColor; + @Shadow @NotNull private CloudStatus prevCloudsType; + @Shadow private boolean generateClouds; + @Shadow @NotNull private VertexBuffer cloudBuffer; + @Unique private boolean initializedClouds = false; + private static float previousPartialTicks = 0; - @Inject(at = @At("RETURN"), method = "renderClouds(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/math/Matrix4f;FDDD)V") - private void renderClouds(PoseStack modelViewMatrixStack, Matrix4f projectionMatrix, float partialTicks, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, CallbackInfo callback) - { + public MixinWorldRenderer() { + throw new NullPointerException("Null cannot be cast to non-null type."); + } + + @Inject(method = "renderClouds", at = @At("HEAD"), cancellable = true) + public void renderClouds(PoseStack poseStack, Matrix4f model, float tickDelta, double cameraX, double cameraY, double cameraZ, CallbackInfo ci) { + TextureManager textureManager = Minecraft.getInstance().getTextureManager(); + registerClouds(textureManager); + NoiseCloudHandler.update(); + + if (minecraft.level.dimension() == ClientLevel.OVERWORLD) { + CloudTexture cloudTexture = NoiseCloudHandler.cloudTextures.get(NoiseCloudHandler.cloudTextures.size() - 1); + renderCloudLayer(poseStack, model, tickDelta, cameraX, cameraY, cameraZ, Config.Client.Graphics.CloudQuality.cloudHeight, 0, 1, 1, cloudTexture.resourceLocation); + } + + ci.cancel(); + // get the partial ticks since renderChunkLayer doesn't // have access to them - previousPartialTicks = partialTicks; + previousPartialTicks = tickDelta; } // HEAD or RETURN @@ -70,4 +121,189 @@ public class MixinWorldRenderer ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks); } } + + + + + + + + + // TODO: Move these outside of the mixin + // When moved out then put credit to https://github.com/misterslime/fabulousclouds-fabric + + private void registerClouds(TextureManager textureManager) { + if (!this.initializedClouds) { + Random random = new Random(); + + NoiseCloudHandler.initCloudTextures(CLOUDS_LOCATION); + + for(CloudTexture cloudTexture : NoiseCloudHandler.cloudTextures) { + cloudTexture.initNoise(random); + + DynamicTexture texture = cloudTexture.getNativeImage(); + textureManager.register(cloudTexture.resourceLocation, texture); + cloudTexture.setTexture(texture); + } + + this.initializedClouds = true; + } + } + + private void renderCloudLayer(PoseStack poseStack, Matrix4f model, float tickDelta, double cameraX, double cameraY, double cameraZ, float cloudHeight, float cloudOffset, float cloudScale, float speedMod, ResourceLocation resourceLocation) { + RenderSystem.disableCull(); + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.depthMask(true); + float scale = 12.0F * cloudScale; + double speed = ((this.ticks + tickDelta) * (0.03F * speedMod)); + double posX = (cameraX + speed) / scale; + double posY = (cloudHeight - (float) cameraY + cloudOffset) / cloudScale; + double posZ = cameraZ / scale + 0.33000001311302185D; + posX -= Math.floor(posX / 2048.0D) * 2048; + posZ -= Math.floor(posZ / 2048.0D) * 2048; + float adjustedX = (float) (posX - (double) Math.floor(posX)); + float adjustedY = (float) (posY / 4.0D - (double) Math.floor(posY / 4.0D)) * 4.0F; + float adjustedZ = (float) (posZ - (double) Math.floor(posZ)); + Vec3 cloudColor = minecraft.level.getCloudColor(tickDelta); + int floorX = (int) Math.floor(posX); + int floorY = (int) Math.floor(posY / 4.0D); + int floorZ = (int) Math.floor(posZ); + if (floorX != this.prevCloudX || floorY != this.prevCloudY || floorZ != this.prevCloudZ || this.minecraft.options.getCloudsType() != this.prevCloudsType || this.prevCloudColor.distanceToSqr(cloudColor) > 2.0E-4D) { + this.prevCloudX = floorX; + this.prevCloudY = floorY; + this.prevCloudZ = floorZ; + this.prevCloudColor = cloudColor; + this.prevCloudsType = this.minecraft.options.getCloudsType(); + this.generateClouds = true; + } + + RenderSystem.setShader(GameRenderer::getPositionTexColorNormalShader); + if (this.generateClouds) { + this.generateClouds = false; + Tesselator tessellator = Tesselator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuilder(); + if (this.cloudBuffer != null) this.cloudBuffer.close(); + + this.cloudBuffer = new VertexBuffer(); + this.buildCloudLayer(bufferBuilder, posX, posY, posZ, cloudOffset, cloudScale, cloudColor); + bufferBuilder.end(); + this.cloudBuffer.upload(bufferBuilder); + } + + RenderSystem.setShaderTexture(0, resourceLocation); + FogRenderer.levelFogColor(); + poseStack.pushPose(); + poseStack.scale(scale, cloudScale, scale); + poseStack.translate(-adjustedX, adjustedY, -adjustedZ); + if (this.cloudBuffer != null) { + int cloudMainIndex = this.prevCloudsType == CloudStatus.FANCY ? 0 : 1; + + for (int cloudIndex = 1; cloudMainIndex <= cloudIndex; ++cloudMainIndex) { + if (cloudMainIndex == 0) { + RenderSystem.colorMask(false, false, false, false); + } else { + RenderSystem.colorMask(true, true, true, true); + } + + ShaderInstance shader = RenderSystem.getShader(); + this.cloudBuffer.drawWithShader(poseStack.last().pose(), model, shader); + } + } + + poseStack.popPose(); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.enableCull(); + RenderSystem.disableBlend(); + } + + private void buildCloudLayer(BufferBuilder bufferBuilder, double cloudX, double cloudY, double cloudZ, float offset, float scale, Vec3 color) { + float lowpFracAccur = (float) Math.pow(2.0, -8); + float mediumpFracAccur = (float) Math.pow(2.0, -10); + float viewDistance = 8; + float cloudThickness = 4.0f; + float adjustedCloudX = (float)Math.floor(cloudX) * lowpFracAccur; + float adjustedCloudZ = (float)Math.floor(cloudZ) * lowpFracAccur; + float redTop = (float)color.x; + float greenTop = (float)color.y; + float blueTop = (float)color.z; + float redEW = redTop * 0.9f; + float greenEW = greenTop * 0.9f; + float blueEW = blueTop * 0.9f; + float redBottom = redTop * 0.7f; + float greenBottom = greenTop * 0.7f; + float blueBottom = blueTop * 0.7f; + float redNS = redTop * 0.8f; + float greenNS = greenTop * 0.8f; + float blueNS = blueTop * 0.8f; + bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR_NORMAL); + float adjustedCloudY = (float)Math.floor(cloudY / cloudThickness) * cloudThickness; + + if (this.prevCloudsType == CloudStatus.FANCY) { + int scaledViewDistance = (int) (((Config.Client.Graphics.CloudQuality.extendClouds ? Config.Client.Graphics.Quality.lodChunkRenderDistance : minecraft.options.renderDistance) / 2) / scale) / 2; + + for (int x = -scaledViewDistance - 1; x <= scaledViewDistance; ++x) { + for (int z = -scaledViewDistance - 1; z <= scaledViewDistance; ++z) { + int n3; + float scaledX = x * viewDistance; + float scaledZ = z * viewDistance; + if (adjustedCloudY > -5.0f) { + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + 0.0f, scaledZ + 8.0f).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redBottom, greenBottom, blueBottom, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + 0.0f, scaledZ + 8.0f).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redBottom, greenBottom, blueBottom, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + 0.0f, scaledZ + 0.0f).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redBottom, greenBottom, blueBottom, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + 0.0f, scaledZ + 0.0f).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redBottom, greenBottom, blueBottom, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + } + if (adjustedCloudY <= 5.0f) { + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + cloudThickness - mediumpFracAccur, scaledZ + 8.0f).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, 1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + cloudThickness - mediumpFracAccur, scaledZ + 8.0f).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, 1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + cloudThickness - mediumpFracAccur, scaledZ + 0.0f).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, 1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + cloudThickness - mediumpFracAccur, scaledZ + 0.0f).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, 1.0f, 0.0f).endVertex(); + } + if (x > -1) { + for (n3 = 0; n3 < 8; ++n3) { + bufferBuilder.vertex(scaledX + (float)n3 + 0.0f, adjustedCloudY + 0.0f, scaledZ + 8.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(-1.0f, 0.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + (float)n3 + 0.0f, adjustedCloudY + cloudThickness, scaledZ + 8.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(-1.0f, 0.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + (float)n3 + 0.0f, adjustedCloudY + cloudThickness, scaledZ + 0.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(-1.0f, 0.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + (float)n3 + 0.0f, adjustedCloudY + 0.0f, scaledZ + 0.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(-1.0f, 0.0f, 0.0f).endVertex(); + } + } + if (x <= 1) { + for (n3 = 0; n3 < 8; ++n3) { + bufferBuilder.vertex(scaledX + (float)n3 + 1.0f - mediumpFracAccur, adjustedCloudY + 0.0f, scaledZ + 8.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(1.0f, 0.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + (float)n3 + 1.0f - mediumpFracAccur, adjustedCloudY + cloudThickness, scaledZ + 8.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(1.0f, 0.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + (float)n3 + 1.0f - mediumpFracAccur, adjustedCloudY + cloudThickness, scaledZ + 0.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(1.0f, 0.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + (float)n3 + 1.0f - mediumpFracAccur, adjustedCloudY + 0.0f, scaledZ + 0.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(1.0f, 0.0f, 0.0f).endVertex(); + } + } + if (z > -1) { + for (n3 = 0; n3 < 8; ++n3) { + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + cloudThickness, scaledZ + (float)n3 + 0.0f).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, -1.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + cloudThickness, scaledZ + (float)n3 + 0.0f).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, -1.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + 0.0f, scaledZ + (float)n3 + 0.0f).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, -1.0f).endVertex(); + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + 0.0f, scaledZ + (float)n3 + 0.0f).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, -1.0f).endVertex(); + } + } + if (z > 1) continue; + for (n3 = 0; n3 < 8; ++n3) { + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + cloudThickness, scaledZ + (float)n3 + 1.0f - mediumpFracAccur).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, 1.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + cloudThickness, scaledZ + (float)n3 + 1.0f - mediumpFracAccur).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, 1.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + 0.0f, scaledZ + (float)n3 + 1.0f - mediumpFracAccur).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, 1.0f).endVertex(); + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + 0.0f, scaledZ + (float)n3 + 1.0f - mediumpFracAccur).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, 1.0f).endVertex(); + } + } + } + } else { + int scaledRenderDistance = (int) ((Config.Client.Graphics.CloudQuality.extendClouds ? Config.Client.Graphics.Quality.lodChunkRenderDistance : minecraft.options.renderDistance) / scale); + + for (int x = -scaledRenderDistance; x < scaledRenderDistance; x += scaledRenderDistance) { + for (int z = -scaledRenderDistance; z < scaledRenderDistance; z += scaledRenderDistance) { + bufferBuilder.vertex(x, adjustedCloudY, z + scaledRenderDistance).uv((float)x * lowpFracAccur + adjustedCloudX, (float)(z + scaledRenderDistance) * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(x + scaledRenderDistance, adjustedCloudY, z + scaledRenderDistance).uv((float)(x + scaledRenderDistance) * lowpFracAccur + adjustedCloudX, (float)(z + scaledRenderDistance) * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(x + scaledRenderDistance, adjustedCloudY, z).uv((float)(x + scaledRenderDistance) * lowpFracAccur + adjustedCloudX, (float)z * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(x, adjustedCloudY, z).uv((float)x * lowpFracAccur + adjustedCloudX, (float)z * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + } + } + } + } } diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/MixinWorldRenderer.java b/forge/src/main/java/com/seibel/lod/forge/mixins/MixinWorldRenderer.java index bccfa4ea5..db59652df 100644 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/MixinWorldRenderer.java +++ b/forge/src/main/java/com/seibel/lod/forge/mixins/MixinWorldRenderer.java @@ -19,20 +19,43 @@ package com.seibel.lod.forge.mixins; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Matrix4f; +import com.seibel.lod.common.Config; +import com.seibel.lod.common.clouds.CloudTexture; +import com.seibel.lod.common.clouds.NoiseCloudHandler; +import com.seibel.lod.common.wrappers.McObjectConverter; +import net.minecraft.client.renderer.LevelRenderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Matrix4f; import com.seibel.lod.core.api.ClientApi; import com.seibel.lod.core.objects.math.Mat4f; -import com.seibel.lod.common.wrappers.McObjectConverter; -import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.RenderType; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.*; +import com.mojang.math.Matrix4f; +import net.minecraft.client.CloudStatus; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.network.chat.ChatType; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.*; + +import java.util.Random; + /** * This class is used to mix in my rendering code * before Minecraft starts rendering blocks. @@ -40,20 +63,49 @@ import net.minecraft.client.renderer.RenderType; * render last event, the LODs would render on top * of the normal terrain. * + * This is also the mixin for rendering the clouds + * + * @author coolGi2007 * @author James Seibel - * @version 9-19-2021 + * @version 12-31-2021 */ @Mixin(LevelRenderer.class) public class MixinWorldRenderer { + @Final @Shadow private static ResourceLocation CLOUDS_LOCATION; + @Shadow private final int ticks; + @Final @Shadow @NotNull private final Minecraft minecraft; + @Shadow private int prevCloudX; + @Shadow private int prevCloudY; + @Shadow private int prevCloudZ; + @Shadow @NotNull private Vec3 prevCloudColor; + @Shadow @NotNull private CloudStatus prevCloudsType; + @Shadow private boolean generateClouds; + @Shadow @NotNull private VertexBuffer cloudBuffer; + @Unique private boolean initializedClouds = false; + private static float previousPartialTicks = 0; - @Inject(at = @At("RETURN"), method = "renderClouds(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/math/Matrix4f;FDDD)V") - private void renderClouds(PoseStack modelViewMatrixStack, Matrix4f projectionMatrix, float partialTicks, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, CallbackInfo callback) - { + public MixinWorldRenderer() { + throw new NullPointerException("Null cannot be cast to non-null type."); + } + + @Inject(method = "renderClouds", at = @At("HEAD"), cancellable = true) + public void renderClouds(PoseStack poseStack, Matrix4f model, float tickDelta, double cameraX, double cameraY, double cameraZ, CallbackInfo ci) { + TextureManager textureManager = Minecraft.getInstance().getTextureManager(); + registerClouds(textureManager); + NoiseCloudHandler.update(); + + if (minecraft.level.dimension() == ClientLevel.OVERWORLD) { + CloudTexture cloudTexture = NoiseCloudHandler.cloudTextures.get(NoiseCloudHandler.cloudTextures.size() - 1); + renderCloudLayer(poseStack, model, tickDelta, cameraX, cameraY, cameraZ, Config.Client.Graphics.CloudQuality.cloudHeight, 0, 1, 1, cloudTexture.resourceLocation); + } + + ci.cancel(); + // get the partial ticks since renderChunkLayer doesn't // have access to them - previousPartialTicks = partialTicks; + previousPartialTicks = tickDelta; } // HEAD or RETURN @@ -69,4 +121,189 @@ public class MixinWorldRenderer ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks); } } -} \ No newline at end of file + + + + + + + + + // TODO: Move these outside of the mixin + // When moved out then put credit to https://github.com/misterslime/fabulousclouds-fabric + + private void registerClouds(TextureManager textureManager) { + if (!this.initializedClouds) { + Random random = new Random(); + + NoiseCloudHandler.initCloudTextures(CLOUDS_LOCATION); + + for(CloudTexture cloudTexture : NoiseCloudHandler.cloudTextures) { + cloudTexture.initNoise(random); + + DynamicTexture texture = cloudTexture.getNativeImage(); + textureManager.register(cloudTexture.resourceLocation, texture); + cloudTexture.setTexture(texture); + } + + this.initializedClouds = true; + } + } + + private void renderCloudLayer(PoseStack poseStack, Matrix4f model, float tickDelta, double cameraX, double cameraY, double cameraZ, float cloudHeight, float cloudOffset, float cloudScale, float speedMod, ResourceLocation resourceLocation) { + RenderSystem.disableCull(); + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.depthMask(true); + float scale = 12.0F * cloudScale; + double speed = ((this.ticks + tickDelta) * (0.03F * speedMod)); + double posX = (cameraX + speed) / scale; + double posY = (cloudHeight - (float) cameraY + cloudOffset) / cloudScale; + double posZ = cameraZ / scale + 0.33000001311302185D; + posX -= Math.floor(posX / 2048.0D) * 2048; + posZ -= Math.floor(posZ / 2048.0D) * 2048; + float adjustedX = (float) (posX - (double) Math.floor(posX)); + float adjustedY = (float) (posY / 4.0D - (double) Math.floor(posY / 4.0D)) * 4.0F; + float adjustedZ = (float) (posZ - (double) Math.floor(posZ)); + Vec3 cloudColor = minecraft.level.getCloudColor(tickDelta); + int floorX = (int) Math.floor(posX); + int floorY = (int) Math.floor(posY / 4.0D); + int floorZ = (int) Math.floor(posZ); + if (floorX != this.prevCloudX || floorY != this.prevCloudY || floorZ != this.prevCloudZ || this.minecraft.options.getCloudsType() != this.prevCloudsType || this.prevCloudColor.distanceToSqr(cloudColor) > 2.0E-4D) { + this.prevCloudX = floorX; + this.prevCloudY = floorY; + this.prevCloudZ = floorZ; + this.prevCloudColor = cloudColor; + this.prevCloudsType = this.minecraft.options.getCloudsType(); + this.generateClouds = true; + } + + RenderSystem.setShader(GameRenderer::getPositionTexColorNormalShader); + if (this.generateClouds) { + this.generateClouds = false; + Tesselator tessellator = Tesselator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuilder(); + if (this.cloudBuffer != null) this.cloudBuffer.close(); + + this.cloudBuffer = new VertexBuffer(); + this.buildCloudLayer(bufferBuilder, posX, posY, posZ, cloudOffset, cloudScale, cloudColor); + bufferBuilder.end(); + this.cloudBuffer.upload(bufferBuilder); + } + + RenderSystem.setShaderTexture(0, resourceLocation); + FogRenderer.levelFogColor(); + poseStack.pushPose(); + poseStack.scale(scale, cloudScale, scale); + poseStack.translate(-adjustedX, adjustedY, -adjustedZ); + if (this.cloudBuffer != null) { + int cloudMainIndex = this.prevCloudsType == CloudStatus.FANCY ? 0 : 1; + + for (int cloudIndex = 1; cloudMainIndex <= cloudIndex; ++cloudMainIndex) { + if (cloudMainIndex == 0) { + RenderSystem.colorMask(false, false, false, false); + } else { + RenderSystem.colorMask(true, true, true, true); + } + + ShaderInstance shader = RenderSystem.getShader(); + this.cloudBuffer.drawWithShader(poseStack.last().pose(), model, shader); + } + } + + poseStack.popPose(); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.enableCull(); + RenderSystem.disableBlend(); + } + + private void buildCloudLayer(BufferBuilder bufferBuilder, double cloudX, double cloudY, double cloudZ, float offset, float scale, Vec3 color) { + float lowpFracAccur = (float) Math.pow(2.0, -8); + float mediumpFracAccur = (float) Math.pow(2.0, -10); + float viewDistance = 8; + float cloudThickness = 4.0f; + float adjustedCloudX = (float)Math.floor(cloudX) * lowpFracAccur; + float adjustedCloudZ = (float)Math.floor(cloudZ) * lowpFracAccur; + float redTop = (float)color.x; + float greenTop = (float)color.y; + float blueTop = (float)color.z; + float redEW = redTop * 0.9f; + float greenEW = greenTop * 0.9f; + float blueEW = blueTop * 0.9f; + float redBottom = redTop * 0.7f; + float greenBottom = greenTop * 0.7f; + float blueBottom = blueTop * 0.7f; + float redNS = redTop * 0.8f; + float greenNS = greenTop * 0.8f; + float blueNS = blueTop * 0.8f; + bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR_NORMAL); + float adjustedCloudY = (float)Math.floor(cloudY / cloudThickness) * cloudThickness; + + if (this.prevCloudsType == CloudStatus.FANCY) { + int scaledViewDistance = (int) (((Config.Client.Graphics.CloudQuality.extendClouds ? Config.Client.Graphics.Quality.lodChunkRenderDistance : minecraft.options.renderDistance) / 2) / scale) / 2; + + for (int x = -scaledViewDistance - 1; x <= scaledViewDistance; ++x) { + for (int z = -scaledViewDistance - 1; z <= scaledViewDistance; ++z) { + int n3; + float scaledX = x * viewDistance; + float scaledZ = z * viewDistance; + if (adjustedCloudY > -5.0f) { + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + 0.0f, scaledZ + 8.0f).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redBottom, greenBottom, blueBottom, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + 0.0f, scaledZ + 8.0f).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redBottom, greenBottom, blueBottom, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + 0.0f, scaledZ + 0.0f).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redBottom, greenBottom, blueBottom, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + 0.0f, scaledZ + 0.0f).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redBottom, greenBottom, blueBottom, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + } + if (adjustedCloudY <= 5.0f) { + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + cloudThickness - mediumpFracAccur, scaledZ + 8.0f).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, 1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + cloudThickness - mediumpFracAccur, scaledZ + 8.0f).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, 1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + cloudThickness - mediumpFracAccur, scaledZ + 0.0f).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, 1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + cloudThickness - mediumpFracAccur, scaledZ + 0.0f).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, 1.0f, 0.0f).endVertex(); + } + if (x > -1) { + for (n3 = 0; n3 < 8; ++n3) { + bufferBuilder.vertex(scaledX + (float)n3 + 0.0f, adjustedCloudY + 0.0f, scaledZ + 8.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(-1.0f, 0.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + (float)n3 + 0.0f, adjustedCloudY + cloudThickness, scaledZ + 8.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(-1.0f, 0.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + (float)n3 + 0.0f, adjustedCloudY + cloudThickness, scaledZ + 0.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(-1.0f, 0.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + (float)n3 + 0.0f, adjustedCloudY + 0.0f, scaledZ + 0.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(-1.0f, 0.0f, 0.0f).endVertex(); + } + } + if (x <= 1) { + for (n3 = 0; n3 < 8; ++n3) { + bufferBuilder.vertex(scaledX + (float)n3 + 1.0f - mediumpFracAccur, adjustedCloudY + 0.0f, scaledZ + 8.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(1.0f, 0.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + (float)n3 + 1.0f - mediumpFracAccur, adjustedCloudY + cloudThickness, scaledZ + 8.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 8.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(1.0f, 0.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + (float)n3 + 1.0f - mediumpFracAccur, adjustedCloudY + cloudThickness, scaledZ + 0.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(1.0f, 0.0f, 0.0f).endVertex(); + bufferBuilder.vertex(scaledX + (float)n3 + 1.0f - mediumpFracAccur, adjustedCloudY + 0.0f, scaledZ + 0.0f).uv((scaledX + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudX, (scaledZ + 0.0f) * lowpFracAccur + adjustedCloudZ).color(redEW, greenEW, blueEW, 0.8f).normal(1.0f, 0.0f, 0.0f).endVertex(); + } + } + if (z > -1) { + for (n3 = 0; n3 < 8; ++n3) { + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + cloudThickness, scaledZ + (float)n3 + 0.0f).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, -1.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + cloudThickness, scaledZ + (float)n3 + 0.0f).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, -1.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + 0.0f, scaledZ + (float)n3 + 0.0f).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, -1.0f).endVertex(); + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + 0.0f, scaledZ + (float)n3 + 0.0f).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, -1.0f).endVertex(); + } + } + if (z > 1) continue; + for (n3 = 0; n3 < 8; ++n3) { + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + cloudThickness, scaledZ + (float)n3 + 1.0f - mediumpFracAccur).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, 1.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + cloudThickness, scaledZ + (float)n3 + 1.0f - mediumpFracAccur).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, 1.0f).endVertex(); + bufferBuilder.vertex(scaledX + 8.0f, adjustedCloudY + 0.0f, scaledZ + (float)n3 + 1.0f - mediumpFracAccur).uv((scaledX + 8.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, 1.0f).endVertex(); + bufferBuilder.vertex(scaledX + 0.0f, adjustedCloudY + 0.0f, scaledZ + (float)n3 + 1.0f - mediumpFracAccur).uv((scaledX + 0.0f) * lowpFracAccur + adjustedCloudX, (scaledZ + (float)n3 + 0.5f) * lowpFracAccur + adjustedCloudZ).color(redNS, greenNS, blueNS, 0.8f).normal(0.0f, 0.0f, 1.0f).endVertex(); + } + } + } + } else { + int scaledRenderDistance = (int) ((Config.Client.Graphics.CloudQuality.extendClouds ? Config.Client.Graphics.Quality.lodChunkRenderDistance : minecraft.options.renderDistance) / scale); + + for (int x = -scaledRenderDistance; x < scaledRenderDistance; x += scaledRenderDistance) { + for (int z = -scaledRenderDistance; z < scaledRenderDistance; z += scaledRenderDistance) { + bufferBuilder.vertex(x, adjustedCloudY, z + scaledRenderDistance).uv((float)x * lowpFracAccur + adjustedCloudX, (float)(z + scaledRenderDistance) * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(x + scaledRenderDistance, adjustedCloudY, z + scaledRenderDistance).uv((float)(x + scaledRenderDistance) * lowpFracAccur + adjustedCloudX, (float)(z + scaledRenderDistance) * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(x + scaledRenderDistance, adjustedCloudY, z).uv((float)(x + scaledRenderDistance) * lowpFracAccur + adjustedCloudX, (float)z * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + bufferBuilder.vertex(x, adjustedCloudY, z).uv((float)x * lowpFracAccur + adjustedCloudX, (float)z * lowpFracAccur + adjustedCloudZ).color(redTop, greenTop, blueTop, 0.8f).normal(0.0f, -1.0f, 0.0f).endVertex(); + } + } + } + } +}