package openblocks.client.renderer.tileentity; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.client.MinecraftForgeClient; import openblocks.client.StencilSkyRenderer; import openblocks.common.block.BlockSky; import openmods.Log; import openmods.renderer.StencilRendererHandler; import openmods.stencil.StencilBitAllocation; import openmods.stencil.StencilPoolManager; import openmods.utils.ColorUtils.RGB; import openmods.utils.render.RenderUtils; import org.lwjgl.opengl.GL11; public class TileEntitySkyRenderer extends TileEntitySpecialRenderer { private boolean initialized; private int displayListBase; private StencilRendererHandler handler; @Override public void renderTileEntityAt(TileEntity te, double x, double y, double z, float partialTickTime) { int meta = te.getBlockMetadata(); if (!BlockSky.isActive(meta)) return; if (!initialized) { intialize(); initialized = true; } GL11.glPushMatrix(); GL11.glTranslated(x, y, z); RGB fog = RenderUtils.getFogColor(); GL11.glColor3f(fog.getR(), fog.getG(), fog.getB()); GL11.glCallList(displayListBase + MinecraftForgeClient.getRenderPass()); // fancy! GL11.glPopMatrix(); handler.markForRender(); } protected void intialize() { displayListBase = GL11.glGenLists(2); final Tessellator tes = new Tessellator(); GL11.glNewList(displayListBase, GL11.GL_COMPILE); renderCube(tes); GL11.glEndList(); StencilBitAllocation bit = StencilPoolManager.pool().acquire(); GL11.glNewList(displayListBase + 1, GL11.GL_COMPILE); if (bit != null) { Log.debug("Stencil bit %d allocated for skyblock rendering", bit.bit); cutHoleInWorld(tes, bit.mask); } else { Log.warn("Failed to allocate stencil bit for skyblock rendering"); } GL11.glEndList(); handler = bit != null? new StencilSkyRenderer(bit.mask) : StencilRendererHandler.DUMMY; } private static void renderCube(Tessellator tes) { tes.startDrawingQuads(); tes.addVertex(0, 0, 0); tes.addVertex(0, 1, 0); tes.addVertex(1, 1, 0); tes.addVertex(1, 0, 0); tes.addVertex(0, 0, 1); tes.addVertex(1, 0, 1); tes.addVertex(1, 1, 1); tes.addVertex(0, 1, 1); tes.addVertex(0, 0, 0); tes.addVertex(0, 0, 1); tes.addVertex(0, 1, 1); tes.addVertex(0, 1, 0); tes.addVertex(1, 0, 0); tes.addVertex(1, 1, 0); tes.addVertex(1, 1, 1); tes.addVertex(1, 0, 1); tes.addVertex(0, 0, 0); tes.addVertex(1, 0, 0); tes.addVertex(1, 0, 1); tes.addVertex(0, 0, 1); tes.addVertex(0, 1, 0); tes.addVertex(0, 1, 1); tes.addVertex(1, 1, 1); tes.addVertex(1, 1, 0); GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_TEXTURE_2D); RenderUtils.disableLightmap(); tes.draw(); RenderUtils.enableLightmap(); GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_LIGHTING); } private static void cutHoleInWorld(Tessellator tes, int stencilMask) { GL11.glStencilMask(stencilMask); GL11.glEnable(GL11.GL_STENCIL_TEST); GL11.glStencilFunc(GL11.GL_ALWAYS, stencilMask, stencilMask); GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE); GL11.glColorMask(false, false, false, false); renderCube(tes); GL11.glColorMask(true, true, true, true); GL11.glStencilMask(0); GL11.glDisable(GL11.GL_STENCIL_TEST); } }