package net.minecraft.client.renderer; import com.mojang.blaze3d.ProjectionType; 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.pipeline.RenderTarget; import com.mojang.blaze3d.systems.CommandEncoder; 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.VertexFormat; import java.util.List; import java.util.OptionalDouble; import java.util.OptionalInt; import java.util.stream.IntStream; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import org.joml.Matrix4fStack; @Environment(EnvType.CLIENT) public class CubeMap { private static final int SIDES = 6; @Nullable private GpuBuffer cubeMapBuffer = null; private final List sides; public CubeMap(ResourceLocation baseImageLocation) { this.sides = IntStream.range(0, 6).mapToObj(i -> baseImageLocation.withPath(baseImageLocation.getPath() + "_" + i + ".png")).toList(); } public void render(Minecraft mc, float pitch, float yaw, float alpha) { if (this.cubeMapBuffer == null) { this.initializeVertices(); } Matrix4f matrix4f = new Matrix4f().setPerspective(1.4835298F, (float)mc.getWindow().getWidth() / mc.getWindow().getHeight(), 0.05F, 10.0F); RenderSystem.backupProjectionMatrix(); RenderSystem.setProjectionMatrix(matrix4f, ProjectionType.PERSPECTIVE); Matrix4fStack matrix4fStack = RenderSystem.getModelViewStack(); matrix4fStack.pushMatrix(); matrix4fStack.rotationX((float) Math.PI); int i = 2; RenderPipeline renderPipeline = RenderPipelines.PANORAMA; RenderTarget renderTarget = Minecraft.getInstance().getMainRenderTarget(); GpuTexture gpuTexture = renderTarget.getColorTexture(); GpuTexture gpuTexture2 = renderTarget.getDepthTexture(); RenderSystem.AutoStorageIndexBuffer autoStorageIndexBuffer = RenderSystem.getSequentialBuffer(VertexFormat.Mode.QUADS); GpuBuffer gpuBuffer = autoStorageIndexBuffer.getBuffer(36); try (RenderPass renderPass = RenderSystem.getDevice() .createCommandEncoder() .createRenderPass(gpuTexture, OptionalInt.empty(), gpuTexture2, OptionalDouble.empty())) { renderPass.setPipeline(renderPipeline); renderPass.setVertexBuffer(0, this.cubeMapBuffer); renderPass.setIndexBuffer(gpuBuffer, autoStorageIndexBuffer.type()); for (int j = 0; j < 4; j++) { matrix4fStack.pushMatrix(); float f = (j % 2 / 2.0F - 0.5F) / 256.0F; float g = (j / 2 / 2.0F - 0.5F) / 256.0F; float h = 0.0F; matrix4fStack.translate(f, g, 0.0F); matrix4fStack.rotateX(pitch * (float) (Math.PI / 180.0)); matrix4fStack.rotateY(yaw * (float) (Math.PI / 180.0)); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, alpha / (j + 1)); for (int k = 0; k < 6; k++) { renderPass.bindSampler("Sampler0", mc.getTextureManager().getTexture((ResourceLocation)this.sides.get(k)).getTexture()); renderPass.drawIndexed(6 * k, 6); } matrix4fStack.popMatrix(); } } RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.restoreProjectionMatrix(); matrix4fStack.popMatrix(); } private void initializeVertices() { this.cubeMapBuffer = RenderSystem.getDevice() .createBuffer(() -> "Cube map vertex buffer", BufferType.VERTICES, BufferUsage.DYNAMIC_WRITE, 24 * DefaultVertexFormat.POSITION_TEX.getVertexSize()); try (ByteBufferBuilder byteBufferBuilder = new ByteBufferBuilder(DefaultVertexFormat.POSITION_TEX.getVertexSize() * 4)) { BufferBuilder bufferBuilder = new BufferBuilder(byteBufferBuilder, VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); bufferBuilder.addVertex(-1.0F, -1.0F, 1.0F).setUv(0.0F, 0.0F); bufferBuilder.addVertex(-1.0F, 1.0F, 1.0F).setUv(0.0F, 1.0F); bufferBuilder.addVertex(1.0F, 1.0F, 1.0F).setUv(1.0F, 1.0F); bufferBuilder.addVertex(1.0F, -1.0F, 1.0F).setUv(1.0F, 0.0F); bufferBuilder.addVertex(1.0F, -1.0F, 1.0F).setUv(0.0F, 0.0F); bufferBuilder.addVertex(1.0F, 1.0F, 1.0F).setUv(0.0F, 1.0F); bufferBuilder.addVertex(1.0F, 1.0F, -1.0F).setUv(1.0F, 1.0F); bufferBuilder.addVertex(1.0F, -1.0F, -1.0F).setUv(1.0F, 0.0F); bufferBuilder.addVertex(1.0F, -1.0F, -1.0F).setUv(0.0F, 0.0F); bufferBuilder.addVertex(1.0F, 1.0F, -1.0F).setUv(0.0F, 1.0F); bufferBuilder.addVertex(-1.0F, 1.0F, -1.0F).setUv(1.0F, 1.0F); bufferBuilder.addVertex(-1.0F, -1.0F, -1.0F).setUv(1.0F, 0.0F); bufferBuilder.addVertex(-1.0F, -1.0F, -1.0F).setUv(0.0F, 0.0F); bufferBuilder.addVertex(-1.0F, 1.0F, -1.0F).setUv(0.0F, 1.0F); bufferBuilder.addVertex(-1.0F, 1.0F, 1.0F).setUv(1.0F, 1.0F); bufferBuilder.addVertex(-1.0F, -1.0F, 1.0F).setUv(1.0F, 0.0F); bufferBuilder.addVertex(-1.0F, -1.0F, -1.0F).setUv(0.0F, 0.0F); bufferBuilder.addVertex(-1.0F, -1.0F, 1.0F).setUv(0.0F, 1.0F); bufferBuilder.addVertex(1.0F, -1.0F, 1.0F).setUv(1.0F, 1.0F); bufferBuilder.addVertex(1.0F, -1.0F, -1.0F).setUv(1.0F, 0.0F); bufferBuilder.addVertex(-1.0F, 1.0F, 1.0F).setUv(0.0F, 0.0F); bufferBuilder.addVertex(-1.0F, 1.0F, -1.0F).setUv(0.0F, 1.0F); bufferBuilder.addVertex(1.0F, 1.0F, -1.0F).setUv(1.0F, 1.0F); bufferBuilder.addVertex(1.0F, 1.0F, 1.0F).setUv(1.0F, 0.0F); try (MeshData meshData = bufferBuilder.buildOrThrow()) { CommandEncoder commandEncoder = RenderSystem.getDevice().createCommandEncoder(); commandEncoder.writeToBuffer(this.cubeMapBuffer, meshData.vertexBuffer(), 0); } } } public void registerTextures(TextureManager textureManager) { for (ResourceLocation resourceLocation : this.sides) { textureManager.registerForNextReload(resourceLocation); } } }