package net.minecraft.client.renderer; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexBuffer; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexFormat.Mode; import com.mojang.math.Axis; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.renderer.MultiBufferSource.BufferSource; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ARGB; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Matrix4fStack; import org.joml.Vector3f; @Environment(EnvType.CLIENT) public class SkyRenderer implements AutoCloseable { private static final ResourceLocation SUN_LOCATION = ResourceLocation.withDefaultNamespace("textures/environment/sun.png"); private static final ResourceLocation MOON_LOCATION = ResourceLocation.withDefaultNamespace("textures/environment/moon_phases.png"); public static final ResourceLocation END_SKY_LOCATION = ResourceLocation.withDefaultNamespace("textures/environment/end_sky.png"); private static final float SKY_DISC_RADIUS = 512.0F; private final VertexBuffer starBuffer = VertexBuffer.uploadStatic(Mode.QUADS, DefaultVertexFormat.POSITION, this::buildStars); private final VertexBuffer topSkyBuffer = VertexBuffer.uploadStatic( Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION, vertexConsumer -> this.buildSkyDisc(vertexConsumer, 16.0F) ); private final VertexBuffer bottomSkyBuffer = VertexBuffer.uploadStatic( Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION, vertexConsumer -> this.buildSkyDisc(vertexConsumer, -16.0F) ); private final VertexBuffer endSkyBuffer = VertexBuffer.uploadStatic(Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR, this::buildEndSky); private void buildStars(VertexConsumer buffer) { RandomSource randomSource = RandomSource.create(10842L); int i = 1500; float f = 100.0F; for (int j = 0; j < 1500; j++) { float g = randomSource.nextFloat() * 2.0F - 1.0F; float h = randomSource.nextFloat() * 2.0F - 1.0F; float k = randomSource.nextFloat() * 2.0F - 1.0F; float l = 0.15F + randomSource.nextFloat() * 0.1F; float m = Mth.lengthSquared(g, h, k); if (!(m <= 0.010000001F) && !(m >= 1.0F)) { Vector3f vector3f = new Vector3f(g, h, k).normalize(100.0F); float n = (float)(randomSource.nextDouble() * (float) Math.PI * 2.0); Matrix3f matrix3f = new Matrix3f().rotateTowards(new Vector3f(vector3f).negate(), new Vector3f(0.0F, 1.0F, 0.0F)).rotateZ(-n); buffer.addVertex(new Vector3f(l, -l, 0.0F).mul(matrix3f).add(vector3f)); buffer.addVertex(new Vector3f(l, l, 0.0F).mul(matrix3f).add(vector3f)); buffer.addVertex(new Vector3f(-l, l, 0.0F).mul(matrix3f).add(vector3f)); buffer.addVertex(new Vector3f(-l, -l, 0.0F).mul(matrix3f).add(vector3f)); } } } private void buildSkyDisc(VertexConsumer buffer, float y) { float f = Math.signum(y) * 512.0F; buffer.addVertex(0.0F, y, 0.0F); for (int i = -180; i <= 180; i += 45) { buffer.addVertex(f * Mth.cos(i * (float) (Math.PI / 180.0)), y, 512.0F * Mth.sin(i * (float) (Math.PI / 180.0))); } } public void renderSkyDisc(float red, float green, float blue) { RenderSystem.setShaderColor(red, green, blue, 1.0F); this.topSkyBuffer.drawWithRenderType(RenderType.sky()); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); } public void renderDarkDisc(PoseStack poseStack) { RenderSystem.setShaderColor(0.0F, 0.0F, 0.0F, 1.0F); poseStack.pushPose(); poseStack.translate(0.0F, 12.0F, 0.0F); this.bottomSkyBuffer.drawWithRenderType(RenderType.sky()); poseStack.popPose(); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); } public void renderSunMoonAndStars( PoseStack poseStack, BufferSource bufferSource, float timeOfDay, int moonPhase, float rainLevel, float starBrightness, FogParameters fog ) { poseStack.pushPose(); poseStack.mulPose(Axis.YP.rotationDegrees(-90.0F)); poseStack.mulPose(Axis.XP.rotationDegrees(timeOfDay * 360.0F)); this.renderSun(rainLevel, bufferSource, poseStack); this.renderMoon(moonPhase, rainLevel, bufferSource, poseStack); bufferSource.endBatch(); if (starBrightness > 0.0F) { this.renderStars(fog, starBrightness, poseStack); } poseStack.popPose(); } private void renderSun(float alpha, MultiBufferSource bufferSource, PoseStack poseStack) { float f = 30.0F; float g = 100.0F; VertexConsumer vertexConsumer = bufferSource.getBuffer(RenderType.celestial(SUN_LOCATION)); int i = ARGB.white(alpha); Matrix4f matrix4f = poseStack.last().pose(); vertexConsumer.addVertex(matrix4f, -30.0F, 100.0F, -30.0F).setUv(0.0F, 0.0F).setColor(i); vertexConsumer.addVertex(matrix4f, 30.0F, 100.0F, -30.0F).setUv(1.0F, 0.0F).setColor(i); vertexConsumer.addVertex(matrix4f, 30.0F, 100.0F, 30.0F).setUv(1.0F, 1.0F).setColor(i); vertexConsumer.addVertex(matrix4f, -30.0F, 100.0F, 30.0F).setUv(0.0F, 1.0F).setColor(i); } private void renderMoon(int phase, float alpha, MultiBufferSource bufferSource, PoseStack poseStack) { float f = 20.0F; int i = phase % 4; int j = phase / 4 % 2; float g = (i + 0) / 4.0F; float h = (j + 0) / 2.0F; float k = (i + 1) / 4.0F; float l = (j + 1) / 2.0F; float m = 100.0F; VertexConsumer vertexConsumer = bufferSource.getBuffer(RenderType.celestial(MOON_LOCATION)); int n = ARGB.white(alpha); Matrix4f matrix4f = poseStack.last().pose(); vertexConsumer.addVertex(matrix4f, -20.0F, -100.0F, 20.0F).setUv(k, l).setColor(n); vertexConsumer.addVertex(matrix4f, 20.0F, -100.0F, 20.0F).setUv(g, l).setColor(n); vertexConsumer.addVertex(matrix4f, 20.0F, -100.0F, -20.0F).setUv(g, h).setColor(n); vertexConsumer.addVertex(matrix4f, -20.0F, -100.0F, -20.0F).setUv(k, h).setColor(n); } private void renderStars(FogParameters fog, float starBrightness, PoseStack poseStack) { Matrix4fStack matrix4fStack = RenderSystem.getModelViewStack(); matrix4fStack.pushMatrix(); matrix4fStack.mul(poseStack.last().pose()); RenderSystem.setShaderColor(starBrightness, starBrightness, starBrightness, starBrightness); RenderSystem.setShaderFog(FogParameters.NO_FOG); this.starBuffer.drawWithRenderType(RenderType.stars()); RenderSystem.setShaderFog(fog); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); matrix4fStack.popMatrix(); } public void renderSunriseAndSunset(PoseStack poseStack, BufferSource bufferSource, float sunAngle, int color) { poseStack.pushPose(); poseStack.mulPose(Axis.XP.rotationDegrees(90.0F)); float f = Mth.sin(sunAngle) < 0.0F ? 180.0F : 0.0F; poseStack.mulPose(Axis.ZP.rotationDegrees(f)); poseStack.mulPose(Axis.ZP.rotationDegrees(90.0F)); Matrix4f matrix4f = poseStack.last().pose(); VertexConsumer vertexConsumer = bufferSource.getBuffer(RenderType.sunriseSunset()); float g = ARGB.alphaFloat(color); vertexConsumer.addVertex(matrix4f, 0.0F, 100.0F, 0.0F).setColor(color); int i = ARGB.transparent(color); int j = 16; for (int k = 0; k <= 16; k++) { float h = k * (float) (Math.PI * 2) / 16.0F; float l = Mth.sin(h); float m = Mth.cos(h); vertexConsumer.addVertex(matrix4f, l * 120.0F, m * 120.0F, -m * 40.0F * g).setColor(i); } poseStack.popPose(); } private void buildEndSky(VertexConsumer buffer) { for (int i = 0; i < 6; i++) { Matrix4f matrix4f = new Matrix4f(); switch (i) { case 1: matrix4f.rotationX((float) (Math.PI / 2)); break; case 2: matrix4f.rotationX((float) (-Math.PI / 2)); break; case 3: matrix4f.rotationX((float) Math.PI); break; case 4: matrix4f.rotationZ((float) (Math.PI / 2)); break; case 5: matrix4f.rotationZ((float) (-Math.PI / 2)); } buffer.addVertex(matrix4f, -100.0F, -100.0F, -100.0F).setUv(0.0F, 0.0F).setColor(-14145496); buffer.addVertex(matrix4f, -100.0F, -100.0F, 100.0F).setUv(0.0F, 16.0F).setColor(-14145496); buffer.addVertex(matrix4f, 100.0F, -100.0F, 100.0F).setUv(16.0F, 16.0F).setColor(-14145496); buffer.addVertex(matrix4f, 100.0F, -100.0F, -100.0F).setUv(16.0F, 0.0F).setColor(-14145496); } } public void renderEndSky() { this.endSkyBuffer.drawWithRenderType(RenderType.endSky()); } public void close() { this.starBuffer.close(); this.topSkyBuffer.close(); this.bottomSkyBuffer.close(); this.endSkyBuffer.close(); } }