package gminers.glasspane.shadowbox; import gminers.kitchensink.Rendering; import lombok.Getter; import lombok.Setter; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; import org.lwjgl.util.glu.Project; /** * A Shadowbox that acts like the panorama shown in the background of the Minecraft main menu. * * @author Aesen Vismea * */ public class PanoramaShadowbox extends PaneShadowbox { private static int panoramaTimer; private final Minecraft mc = Minecraft.getMinecraft(); private ResourceLocation panoramaTexture; private DynamicTexture viewportTexture; /** * Whether or not this shadowbox should render with a layer of "fog" over it. */ @Getter @Setter private boolean foggy = true; private static final ResourceLocation[] titlePanoramaPaths = new ResourceLocation[] { new ResourceLocation("textures/gui/title/background/panorama_0.png"), new ResourceLocation("textures/gui/title/background/panorama_1.png"), new ResourceLocation("textures/gui/title/background/panorama_2.png"), new ResourceLocation("textures/gui/title/background/panorama_3.png"), new ResourceLocation("textures/gui/title/background/panorama_4.png"), new ResourceLocation("textures/gui/title/background/panorama_5.png") }; private ResourceLocation[] overridePaths = null; /** * Returns a <b>clone</b> of the paths currently being used to override the default panorama. */ public ResourceLocation[] getOverridePaths() { return overridePaths == null ? null : overridePaths.clone(); } /** * Sets the overrides for this panorama. Passing null resets it to the default used by the main menu. * * @param overridePaths * The array of paths to use as an override. Must be 6 elements long, and contain no null elements. */ public void setOverridePaths(final ResourceLocation[] overridePaths) { if (overridePaths.length != 6) throw new IllegalArgumentException("Override paths array is incorrectly sized!"); for (int i = 0; i < overridePaths.length; i++) { if (overridePaths[i] == null) throw new NullPointerException("overridePaths[" + i + "]"); } this.overridePaths = overridePaths.clone(); } private void drawPanorama(final float partialTick) { Minecraft mc = Minecraft.getMinecraft(); Tessellator tessellator = Tessellator.getInstance(); WorldRenderer worldrenderer = tessellator.getWorldRenderer(); GlStateManager.matrixMode(5889); GlStateManager.pushMatrix(); GlStateManager.loadIdentity(); Project.gluPerspective(120.0F, 1.0F, 0.05F, 10.0F); GlStateManager.matrixMode(5888); GlStateManager.pushMatrix(); GlStateManager.loadIdentity(); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); GlStateManager.rotate(180.0F, 1.0F, 0.0F, 0.0F); GlStateManager.rotate(90.0F, 0.0F, 0.0F, 1.0F); GlStateManager.enableBlend(); GlStateManager.disableAlpha(); GlStateManager.disableCull(); GlStateManager.depthMask(false); GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); byte b0 = 8; for (int k = 0; k < b0 * b0; ++k) { GlStateManager.pushMatrix(); float f1 = ((float)(k % b0) / (float)b0 - 0.5F) / 64.0F; float f2 = ((float)(k / b0) / (float)b0 - 0.5F) / 64.0F; float f3 = 0.0F; GlStateManager.translate(f1, f2, f3); GlStateManager.rotate(MathHelper.sin(((float)panoramaTimer + partialTick) / 400.0F) * 25.0F + 20.0F, 1.0F, 0.0F, 0.0F); GlStateManager.rotate(-((float)panoramaTimer + partialTick) * 0.1F, 0.0F, 1.0F, 0.0F); for (int l = 0; l < 6; ++l) { GlStateManager.pushMatrix(); if (l == 1) { GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F); } if (l == 2) { GlStateManager.rotate(180.0F, 0.0F, 1.0F, 0.0F); } if (l == 3) { GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F); } if (l == 4) { GlStateManager.rotate(90.0F, 1.0F, 0.0F, 0.0F); } if (l == 5) { GlStateManager.rotate(-90.0F, 1.0F, 0.0F, 0.0F); } mc.getTextureManager().bindTexture(overridePaths == null ? titlePanoramaPaths[l] : overridePaths[l]); worldrenderer.startDrawingQuads(); worldrenderer.setColorRGBA_I(16777215, 255 / (k + 1)); float f4 = 0.0F; worldrenderer.addVertexWithUV(-1.0D, -1.0D, 1.0D, (double)(0.0F + f4), (double)(0.0F + f4)); worldrenderer.addVertexWithUV(1.0D, -1.0D, 1.0D, (double)(1.0F - f4), (double)(0.0F + f4)); worldrenderer.addVertexWithUV(1.0D, 1.0D, 1.0D, (double)(1.0F - f4), (double)(1.0F - f4)); worldrenderer.addVertexWithUV(-1.0D, 1.0D, 1.0D, (double)(0.0F + f4), (double)(1.0F - f4)); tessellator.draw(); GlStateManager.popMatrix(); } GlStateManager.popMatrix(); GlStateManager.colorMask(true, true, true, false); } worldrenderer.setTranslation(0.0D, 0.0D, 0.0D); GlStateManager.colorMask(true, true, true, true); GlStateManager.matrixMode(5889); GlStateManager.popMatrix(); GlStateManager.matrixMode(5888); GlStateManager.popMatrix(); GlStateManager.depthMask(true); GlStateManager.enableCull(); GlStateManager.enableDepth(); } private void rotateAndBlurSkybox(final float partialTick) { this.mc.getTextureManager().bindTexture(panoramaTexture); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); GL11.glCopyTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, 0, 0, 256, 256); GlStateManager.enableBlend(); GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); GlStateManager.colorMask(true, true, true, false); Tessellator tessellator = Tessellator.getInstance(); WorldRenderer worldrenderer = tessellator.getWorldRenderer(); worldrenderer.startDrawingQuads(); GlStateManager.disableAlpha(); byte b0 = 3; for (int i = 0; i < b0; ++i) { worldrenderer.setColorRGBA_F(1.0F, 1.0F, 1.0F, 1.0F / (float)(i + 1)); int j = this.width; int k = this.height; float f1 = (float)(i - b0 / 2) / 256.0F; worldrenderer.addVertexWithUV((double)j, (double)k, (double)0, (double)(0.0F + f1), 1.0D); worldrenderer.addVertexWithUV((double)j, 0.0D, (double)0, (double)(1.0F + f1), 1.0D); worldrenderer.addVertexWithUV(0.0D, 0.0D, (double)0, (double)(1.0F + f1), 0.0D); worldrenderer.addVertexWithUV(0.0D, (double)k, (double)0, (double)(0.0F + f1), 0.0D); } tessellator.draw(); GlStateManager.enableAlpha(); GlStateManager.colorMask(true, true, true, true); } private void renderSkybox(final float partialTick) { this.mc.getFramebuffer().unbindFramebuffer(); GlStateManager.viewport(0, 0, 256, 256); drawPanorama(partialTick); rotateAndBlurSkybox(partialTick); rotateAndBlurSkybox(partialTick); rotateAndBlurSkybox(partialTick); rotateAndBlurSkybox(partialTick); rotateAndBlurSkybox(partialTick); rotateAndBlurSkybox(partialTick); rotateAndBlurSkybox(partialTick); this.mc.getFramebuffer().bindFramebuffer(true); GlStateManager.viewport(0, 0, this.mc.displayWidth, this.mc.displayHeight); Tessellator tessellator = Tessellator.getInstance(); WorldRenderer worldrenderer = tessellator.getWorldRenderer(); worldrenderer.startDrawingQuads(); float f1 = this.width > this.height ? 120.0F / (float)this.width : 120.0F / (float)this.height; float f2 = (float)this.height * f1 / 256.0F; float f3 = (float)this.width * f1 / 256.0F; worldrenderer.setColorRGBA_F(1.0F, 1.0F, 1.0F, 1.0F); int k = this.width; int l = this.height; worldrenderer.addVertexWithUV(0.0D, (double)l, (double)0, (double)(0.5F - f2), (double)(0.5F + f3)); worldrenderer.addVertexWithUV((double)k, (double)l, (double)0, (double)(0.5F - f2), (double)(0.5F - f3)); worldrenderer.addVertexWithUV((double)k, 0.0D, (double)0, (double)(0.5F + f2), (double)(0.5F - f3)); worldrenderer.addVertexWithUV(0.0D, 0.0D, (double)0, (double)(0.5F + f2), (double)(0.5F + f3)); tessellator.draw(); } @Override public void render(final int mouseX, final int mouseY, final float partialTicks) { GL11.glDisable(GL11.GL_ALPHA_TEST); this.renderSkybox(partialTicks); GL11.glEnable(GL11.GL_ALPHA_TEST); if (foggy) { Rendering.drawGradientRect(0, 0, this.width, this.height, -0x7F000001, 0x00FFFFFF, 0); Rendering.drawGradientRect(0, 0, this.width, this.height, 0, Integer.MIN_VALUE, 0); } } @Override public void tick() { panoramaTimer++; } @Override public void winch() { viewportTexture = new DynamicTexture(256, 256); panoramaTexture = mc.getTextureManager().getDynamicTextureLocation("background", this.viewportTexture); } }