package net.minecraft.client.renderer; import com.mojang.blaze3d.buffers.BufferType; import com.mojang.blaze3d.buffers.BufferUsage; import com.mojang.blaze3d.buffers.GpuBuffer; import com.mojang.blaze3d.pipeline.RenderPipeline; import com.mojang.blaze3d.systems.RenderPass; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.textures.GpuTexture; import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.ByteBufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.MeshData; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.math.Axis; import java.util.OptionalDouble; import java.util.OptionalInt; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.AbstractTexture; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ARGB; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.util.TriState; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Matrix4fStack; import org.joml.Vector3f; @OnlyIn(Dist.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 static final int SKY_VERTICES = 10; private static final int STAR_COUNT = 1500; private static final int END_SKY_QUAD_COUNT = 6; private final GpuBuffer starBuffer; private final RenderSystem.AutoStorageIndexBuffer starIndices = RenderSystem.getSequentialBuffer(VertexFormat.Mode.QUADS); private final GpuBuffer topSkyBuffer; private final GpuBuffer bottomSkyBuffer; private final GpuBuffer endSkyBuffer; private int starIndexCount; public SkyRenderer() { this.starBuffer = this.buildStars(); this.endSkyBuffer = buildEndSky(); try (ByteBufferBuilder bytebufferbuilder = new ByteBufferBuilder(10 * DefaultVertexFormat.POSITION.getVertexSize())) { BufferBuilder bufferbuilder = new BufferBuilder(bytebufferbuilder, VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION); this.buildSkyDisc(bufferbuilder, 16.0F); try (MeshData meshdata = bufferbuilder.buildOrThrow()) { this.topSkyBuffer = RenderSystem.getDevice() .createBuffer(() -> "Top sky vertex buffer", BufferType.VERTICES, BufferUsage.STATIC_WRITE, meshdata.vertexBuffer()); } bufferbuilder = new BufferBuilder(bytebufferbuilder, VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION); this.buildSkyDisc(bufferbuilder, -16.0F); try (MeshData meshdata1 = bufferbuilder.buildOrThrow()) { this.bottomSkyBuffer = RenderSystem.getDevice() .createBuffer(() -> "Bottom sky vertex buffer", BufferType.VERTICES, BufferUsage.STATIC_WRITE, meshdata1.vertexBuffer()); } } } private GpuBuffer buildStars() { RandomSource randomsource = RandomSource.create(10842L); float f = 100.0F; GpuBuffer gpubuffer; try (ByteBufferBuilder bytebufferbuilder = new ByteBufferBuilder(DefaultVertexFormat.POSITION.getVertexSize() * 1500 * 4)) { BufferBuilder bufferbuilder = new BufferBuilder(bytebufferbuilder, VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION); for (int i = 0; i < 1500; i++) { float f1 = randomsource.nextFloat() * 2.0F - 1.0F; float f2 = randomsource.nextFloat() * 2.0F - 1.0F; float f3 = randomsource.nextFloat() * 2.0F - 1.0F; float f4 = 0.15F + randomsource.nextFloat() * 0.1F; float f5 = Mth.lengthSquared(f1, f2, f3); if (!(f5 <= 0.010000001F) && !(f5 >= 1.0F)) { Vector3f vector3f = new Vector3f(f1, f2, f3).normalize(100.0F); float f6 = (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(-f6); bufferbuilder.addVertex(new Vector3f(f4, -f4, 0.0F).mul(matrix3f).add(vector3f)); bufferbuilder.addVertex(new Vector3f(f4, f4, 0.0F).mul(matrix3f).add(vector3f)); bufferbuilder.addVertex(new Vector3f(-f4, f4, 0.0F).mul(matrix3f).add(vector3f)); bufferbuilder.addVertex(new Vector3f(-f4, -f4, 0.0F).mul(matrix3f).add(vector3f)); } } try (MeshData meshdata = bufferbuilder.buildOrThrow()) { this.starIndexCount = meshdata.drawState().indexCount(); gpubuffer = RenderSystem.getDevice() .createBuffer(() -> "Stars vertex buffer", BufferType.VERTICES, BufferUsage.STATIC_WRITE, meshdata.vertexBuffer()); } } return gpubuffer; } private void buildSkyDisc(VertexConsumer p_375466_, float p_363584_) { float f = Math.signum(p_363584_) * 512.0F; p_375466_.addVertex(0.0F, p_363584_, 0.0F); for (int i = -180; i <= 180; i += 45) { p_375466_.addVertex(f * Mth.cos(i * (float) (Math.PI / 180.0)), p_363584_, 512.0F * Mth.sin(i * (float) (Math.PI / 180.0))); } } public void renderSkyDisc(float p_369198_, float p_369913_, float p_362432_) { RenderSystem.setShaderColor(p_369198_, p_369913_, p_362432_, 1.0F); GpuTexture gputexture = Minecraft.getInstance().getMainRenderTarget().getColorTexture(); GpuTexture gputexture1 = Minecraft.getInstance().getMainRenderTarget().getDepthTexture(); try (RenderPass renderpass = RenderSystem.getDevice() .createCommandEncoder() .createRenderPass(gputexture, OptionalInt.empty(), gputexture1, OptionalDouble.empty())) { renderpass.setPipeline(RenderPipelines.SKY); renderpass.setVertexBuffer(0, this.topSkyBuffer); renderpass.draw(0, 10); } RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); } public void renderDarkDisc() { RenderSystem.setShaderColor(0.0F, 0.0F, 0.0F, 1.0F); Matrix4fStack matrix4fstack = RenderSystem.getModelViewStack(); matrix4fstack.pushMatrix(); matrix4fstack.translate(0.0F, 12.0F, 0.0F); GpuTexture gputexture = Minecraft.getInstance().getMainRenderTarget().getColorTexture(); GpuTexture gputexture1 = Minecraft.getInstance().getMainRenderTarget().getDepthTexture(); try (RenderPass renderpass = RenderSystem.getDevice() .createCommandEncoder() .createRenderPass(gputexture, OptionalInt.empty(), gputexture1, OptionalDouble.empty())) { renderpass.setPipeline(RenderPipelines.SKY); renderpass.setVertexBuffer(0, this.bottomSkyBuffer); renderpass.draw(0, 10); } matrix4fstack.popMatrix(); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); } public void renderSunMoonAndStars( PoseStack p_362673_, MultiBufferSource.BufferSource p_376689_, float p_369057_, int p_364932_, float p_366540_, float p_368016_, FogParameters p_362209_ ) { p_362673_.pushPose(); p_362673_.mulPose(Axis.YP.rotationDegrees(-90.0F)); p_362673_.mulPose(Axis.XP.rotationDegrees(p_369057_ * 360.0F)); this.renderSun(p_366540_, p_376689_, p_362673_); this.renderMoon(p_364932_, p_366540_, p_376689_, p_362673_); p_376689_.endBatch(); if (p_368016_ > 0.0F) { this.renderStars(p_362209_, p_368016_, p_362673_); } p_362673_.popPose(); } private void renderSun(float p_363755_, MultiBufferSource p_376565_, PoseStack p_369287_) { float f = 30.0F; float f1 = 100.0F; VertexConsumer vertexconsumer = p_376565_.getBuffer(RenderType.celestial(SUN_LOCATION)); int i = ARGB.white(p_363755_); Matrix4f matrix4f = p_369287_.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 p_367893_, float p_364034_, MultiBufferSource p_377520_, PoseStack p_369177_) { float f = 20.0F; int i = p_367893_ % 4; int j = p_367893_ / 4 % 2; float f1 = (i + 0) / 4.0F; float f2 = (j + 0) / 2.0F; float f3 = (i + 1) / 4.0F; float f4 = (j + 1) / 2.0F; float f5 = 100.0F; VertexConsumer vertexconsumer = p_377520_.getBuffer(RenderType.celestial(MOON_LOCATION)); int k = ARGB.white(p_364034_); Matrix4f matrix4f = p_369177_.last().pose(); vertexconsumer.addVertex(matrix4f, -20.0F, -100.0F, 20.0F).setUv(f3, f4).setColor(k); vertexconsumer.addVertex(matrix4f, 20.0F, -100.0F, 20.0F).setUv(f1, f4).setColor(k); vertexconsumer.addVertex(matrix4f, 20.0F, -100.0F, -20.0F).setUv(f1, f2).setColor(k); vertexconsumer.addVertex(matrix4f, -20.0F, -100.0F, -20.0F).setUv(f3, f2).setColor(k); } private void renderStars(FogParameters p_362284_, float p_361462_, PoseStack p_364130_) { Matrix4fStack matrix4fstack = RenderSystem.getModelViewStack(); matrix4fstack.pushMatrix(); matrix4fstack.mul(p_364130_.last().pose()); RenderSystem.setShaderColor(p_361462_, p_361462_, p_361462_, p_361462_); RenderSystem.setShaderFog(FogParameters.NO_FOG); RenderPipeline renderpipeline = RenderPipelines.STARS; GpuTexture gputexture = Minecraft.getInstance().getMainRenderTarget().getColorTexture(); GpuTexture gputexture1 = Minecraft.getInstance().getMainRenderTarget().getDepthTexture(); GpuBuffer gpubuffer = this.starIndices.getBuffer(this.starIndexCount); try (RenderPass renderpass = RenderSystem.getDevice() .createCommandEncoder() .createRenderPass(gputexture, OptionalInt.empty(), gputexture1, OptionalDouble.empty())) { renderpass.setPipeline(renderpipeline); renderpass.setVertexBuffer(0, this.starBuffer); renderpass.setIndexBuffer(gpubuffer, this.starIndices.type()); renderpass.drawIndexed(0, this.starIndexCount); } RenderSystem.setShaderFog(p_362284_); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); matrix4fstack.popMatrix(); } public void renderSunriseAndSunset(PoseStack p_365939_, MultiBufferSource.BufferSource p_377149_, float p_368996_, int p_365467_) { p_365939_.pushPose(); p_365939_.mulPose(Axis.XP.rotationDegrees(90.0F)); float f = Mth.sin(p_368996_) < 0.0F ? 180.0F : 0.0F; p_365939_.mulPose(Axis.ZP.rotationDegrees(f)); p_365939_.mulPose(Axis.ZP.rotationDegrees(90.0F)); Matrix4f matrix4f = p_365939_.last().pose(); VertexConsumer vertexconsumer = p_377149_.getBuffer(RenderType.sunriseSunset()); float f1 = ARGB.alphaFloat(p_365467_); vertexconsumer.addVertex(matrix4f, 0.0F, 100.0F, 0.0F).setColor(p_365467_); int i = ARGB.transparent(p_365467_); int j = 16; for (int k = 0; k <= 16; k++) { float f2 = k * (float) (Math.PI * 2) / 16.0F; float f3 = Mth.sin(f2); float f4 = Mth.cos(f2); vertexconsumer.addVertex(matrix4f, f3 * 120.0F, f4 * 120.0F, -f4 * 40.0F * f1).setColor(i); } p_365939_.popPose(); } private static GpuBuffer buildEndSky() { GpuBuffer gpubuffer; try (ByteBufferBuilder bytebufferbuilder = new ByteBufferBuilder(24 * DefaultVertexFormat.POSITION_TEX_COLOR.getVertexSize())) { BufferBuilder bufferbuilder = new BufferBuilder(bytebufferbuilder, VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); 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)); } bufferbuilder.addVertex(matrix4f, -100.0F, -100.0F, -100.0F).setUv(0.0F, 0.0F).setColor(-14145496); bufferbuilder.addVertex(matrix4f, -100.0F, -100.0F, 100.0F).setUv(0.0F, 16.0F).setColor(-14145496); bufferbuilder.addVertex(matrix4f, 100.0F, -100.0F, 100.0F).setUv(16.0F, 16.0F).setColor(-14145496); bufferbuilder.addVertex(matrix4f, 100.0F, -100.0F, -100.0F).setUv(16.0F, 0.0F).setColor(-14145496); } try (MeshData meshdata = bufferbuilder.buildOrThrow()) { gpubuffer = RenderSystem.getDevice() .createBuffer(() -> "End sky vertex buffer", BufferType.VERTICES, BufferUsage.STATIC_WRITE, meshdata.vertexBuffer()); } } return gpubuffer; } public void renderEndSky() { TextureManager texturemanager = Minecraft.getInstance().getTextureManager(); AbstractTexture abstracttexture = texturemanager.getTexture(END_SKY_LOCATION); abstracttexture.setFilter(TriState.FALSE, false); RenderSystem.AutoStorageIndexBuffer rendersystem$autostorageindexbuffer = RenderSystem.getSequentialBuffer(VertexFormat.Mode.QUADS); GpuBuffer gpubuffer = rendersystem$autostorageindexbuffer.getBuffer(36); GpuTexture gputexture = Minecraft.getInstance().getMainRenderTarget().getColorTexture(); GpuTexture gputexture1 = Minecraft.getInstance().getMainRenderTarget().getDepthTexture(); try (RenderPass renderpass = RenderSystem.getDevice() .createCommandEncoder() .createRenderPass(gputexture, OptionalInt.empty(), gputexture1, OptionalDouble.empty())) { renderpass.setPipeline(RenderPipelines.END_SKY); renderpass.bindSampler("Sampler0", abstracttexture.getTexture()); renderpass.setVertexBuffer(0, this.endSkyBuffer); renderpass.setIndexBuffer(gpubuffer, rendersystem$autostorageindexbuffer.type()); renderpass.drawIndexed(0, 36); } } @Override public void close() { this.starBuffer.close(); this.topSkyBuffer.close(); this.bottomSkyBuffer.close(); this.endSkyBuffer.close(); } }