diff --git a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java index 5b0b2fe06..87da21608 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java @@ -6,7 +6,6 @@ package dan200.computercraft.client.gui; import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.gui.widgets.ComputerSidebar; import dan200.computercraft.client.gui.widgets.WidgetTerminal; @@ -19,6 +18,7 @@ import net.minecraft.util.text.ITextComponent; import javax.annotation.Nonnull; import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER; +import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP; public final class GuiComputer extends ComputerScreenBase { @@ -73,9 +73,10 @@ public final class GuiComputer extends Computer public void renderBg( @Nonnull MatrixStack stack, float partialTicks, int mouseX, int mouseY ) { // Draw a border around the terminal - RenderSystem.color4f( 1, 1, 1, 1 ); - minecraft.getTextureManager().bind( ComputerBorderRenderer.getTexture( family ) ); - ComputerBorderRenderer.render( terminal.x, terminal.y, getBlitOffset(), terminal.getWidth(), terminal.getHeight() ); + ComputerBorderRenderer.render( + ComputerBorderRenderer.getTexture( family ), terminal.x, terminal.y, getBlitOffset(), + FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight() + ); ComputerSidebar.renderBackground( stack, leftPos, topPos + sidebarYOffset ); } } diff --git a/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java index 81893c682..eb7ab0bc7 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java @@ -10,9 +10,9 @@ import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.common.ContainerHeldItem; import dan200.computercraft.shared.media.items.ItemPrintout; -import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.inventory.ContainerScreen; import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.Tessellator; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.text.ITextComponent; @@ -21,6 +21,7 @@ import org.lwjgl.glfw.GLFW; import javax.annotation.Nonnull; import static dan200.computercraft.client.render.PrintoutRenderer.*; +import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP; public class GuiPrintout extends ContainerScreen { @@ -97,10 +98,10 @@ public class GuiPrintout extends ContainerScreen RenderSystem.color4f( 1.0f, 1.0f, 1.0f, 1.0f ); RenderSystem.enableDepthTest(); - IRenderTypeBuffer.Impl renderer = Minecraft.getInstance().renderBuffers().bufferSource(); + IRenderTypeBuffer.Impl renderer = IRenderTypeBuffer.immediate( Tessellator.getInstance().getBuilder() ); Matrix4f matrix = transform.last().pose(); - drawBorder( matrix, renderer, leftPos, topPos, getBlitOffset(), page, pages, book ); - drawText( matrix, renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, text, colours ); + drawBorder( matrix, renderer, leftPos, topPos, getBlitOffset(), page, pages, book, FULL_BRIGHT_LIGHTMAP ); + drawText( matrix, renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours ); renderer.endBatch(); } diff --git a/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java index 44c282f60..056af5604 100644 --- a/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java +++ b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java @@ -6,22 +6,28 @@ package dan200.computercraft.client.gui.widgets; import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.IVertexBuilder; +import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.client.render.text.FixedWidthFontRenderer; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.computer.core.ClientComputer; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.widget.Widget; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.Tessellator; import net.minecraft.util.SharedConstants; import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.text.StringTextComponent; import org.lwjgl.glfw.GLFW; +import org.lwjgl.opengl.GL11; import javax.annotation.Nonnull; import java.util.BitSet; +import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN; import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_HEIGHT; import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_WIDTH; -import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN; public class WidgetTerminal extends Widget { @@ -314,14 +320,23 @@ public class WidgetTerminal extends Widget if( !visible ) return; Matrix4f matrix = transform.last().pose(); Terminal terminal = computer.getTerminal(); + + Minecraft.getInstance().getTextureManager().bind( FixedWidthFontRenderer.FONT ); + RenderSystem.texParameter( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP ); + + IRenderTypeBuffer.Impl renderer = IRenderTypeBuffer.immediate( Tessellator.getInstance().getBuilder() ); + IVertexBuilder buffer = renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ); + if( terminal != null ) { - FixedWidthFontRenderer.drawTerminal( matrix, innerX, innerY, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN ); + FixedWidthFontRenderer.drawTerminal( matrix, buffer, innerX, innerY, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN ); } else { - FixedWidthFontRenderer.drawEmptyTerminal( matrix, x, y, width, height ); + FixedWidthFontRenderer.drawEmptyTerminal( matrix, buffer, x, y, width, height ); } + + renderer.endBatch(); } public static int getWidth( int termWidth ) diff --git a/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java b/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java index 9d410b57c..fceca4040 100644 --- a/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java @@ -5,16 +5,14 @@ */ package dan200.computercraft.client.render; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.IVertexBuilder; import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.computer.core.ComputerFamily; -import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Matrix4f; -import org.lwjgl.opengl.GL11; import javax.annotation.Nonnull; @@ -59,18 +57,19 @@ public class ComputerBorderRenderer private final IVertexBuilder builder; private final int z; private final float r, g, b; + private final int light; - public ComputerBorderRenderer( Matrix4f transform, IVertexBuilder builder, int z, float r, float g, float b ) + public ComputerBorderRenderer( Matrix4f transform, IVertexBuilder builder, int z, int light, float r, float g, float b ) { this.transform = transform; this.builder = builder; this.z = z; + this.light = light; this.r = r; this.g = g; this.b = b; } - @Nonnull public static ResourceLocation getTexture( @Nonnull ComputerFamily family ) { @@ -86,31 +85,22 @@ public class ComputerBorderRenderer } } - public static void render( int x, int y, int z, int width, int height ) + public static RenderType getRenderType( ResourceLocation location ) { - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuilder(); - buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX ); - - render( IDENTITY, buffer, x, y, z, width, height ); - - RenderSystem.enableAlphaTest(); - tessellator.end(); + // See note in RenderTypes about why we use text rather than anything intuitive. + return RenderType.text( location ); } - public static void render( Matrix4f transform, IVertexBuilder buffer, int x, int y, int z, int width, int height ) + public static void render( ResourceLocation location, int x, int y, int z, int light, int width, int height ) { - render( transform, buffer, x, y, z, width, height, 1, 1, 1 ); + IRenderTypeBuffer.Impl source = IRenderTypeBuffer.immediate( Tessellator.getInstance().getBuilder() ); + render( IDENTITY, source.getBuffer( getRenderType( location ) ), x, y, z, light, width, height, false, 1, 1, 1 ); + source.endBatch(); } - public static void render( Matrix4f transform, IVertexBuilder buffer, int x, int y, int z, int width, int height, float r, float g, float b ) + public static void render( Matrix4f transform, IVertexBuilder buffer, int x, int y, int z, int light, int width, int height, boolean withLight, float r, float g, float b ) { - render( transform, buffer, x, y, z, width, height, false, r, g, b ); - } - - public static void render( Matrix4f transform, IVertexBuilder buffer, int x, int y, int z, int width, int height, boolean withLight, float r, float g, float b ) - { - new ComputerBorderRenderer( transform, buffer, z, r, g, b ).doRender( x, y, width, height, withLight ); + new ComputerBorderRenderer( transform, buffer, z, light, r, g, b ).doRender( x, y, width, height, withLight ); } public void doRender( int x, int y, int width, int height, boolean withLight ) @@ -160,9 +150,9 @@ public class ComputerBorderRenderer private void renderTexture( int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight ) { - builder.vertex( transform, x, y + height, z ).color( r, g, b, 1.0f ).uv( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).endVertex(); - builder.vertex( transform, x + width, y + height, z ).color( r, g, b, 1.0f ).uv( (u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).endVertex(); - builder.vertex( transform, x + width, y, z ).color( r, g, b, 1.0f ).uv( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE ).endVertex(); - builder.vertex( transform, x, y, z ).color( r, g, b, 1.0f ).uv( u * TEX_SCALE, v * TEX_SCALE ).endVertex(); + builder.vertex( transform, x, y + height, z ).color( r, g, b, 1.0f ).uv( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).uv2( light ).endVertex(); + builder.vertex( transform, x + width, y + height, z ).color( r, g, b, 1.0f ).uv( (u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).uv2( light ).endVertex(); + builder.vertex( transform, x + width, y, z ).color( r, g, b, 1.0f ).uv( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE ).uv2( light ).endVertex(); + builder.vertex( transform, x, y, z ).color( r, g, b, 1.0f ).uv( u * TEX_SCALE, v * TEX_SCALE ).uv2( light ).endVertex(); } } diff --git a/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java index ac146c895..cd7a73f55 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java @@ -25,9 +25,10 @@ public abstract class ItemMapLikeRenderer * @param transform The matrix transformation stack * @param render The buffer to render to * @param stack The stack to render + * @param light The packed lightmap coordinates. * @see FirstPersonRenderer#renderItemInFirstPerson(AbstractClientPlayerEntity, float, float, Hand, float, ItemStack, float, MatrixStack, IRenderTypeBuffer, int) */ - protected abstract void renderItem( MatrixStack transform, IRenderTypeBuffer render, ItemStack stack ); + protected abstract void renderItem( MatrixStack transform, IRenderTypeBuffer render, ItemStack stack, int light ); protected void renderItemFirstPerson( MatrixStack transform, IRenderTypeBuffer render, int lightTexture, Hand hand, float pitch, float equipProgress, float swingProgress, ItemStack stack ) { @@ -89,7 +90,7 @@ public abstract class ItemMapLikeRenderer transform.mulPose( Vector3f.XP.rotationDegrees( f2 * -45f ) ); transform.mulPose( Vector3f.YP.rotationDegrees( offset * f2 * -30f ) ); - renderItem( transform, render, stack ); + renderItem( transform, render, stack, combinedLight ); transform.popPose(); } @@ -134,6 +135,6 @@ public abstract class ItemMapLikeRenderer transform.mulPose( Vector3f.XP.rotationDegrees( rX * 20.0F ) ); transform.scale( 2.0F, 2.0F, 2.0F ); - renderItem( transform, render, stack ); + renderItem( transform, render, stack, combinedLight ); } } diff --git a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java index 36eb6b180..c5c8b2efa 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java @@ -6,7 +6,7 @@ package dan200.computercraft.client.render; import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.IVertexBuilder; import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.render.text.FixedWidthFontRenderer; import dan200.computercraft.core.terminal.Terminal; @@ -14,23 +14,19 @@ import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.pocket.items.ItemPocketComputer; import dan200.computercraft.shared.util.Colour; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Vector3f; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.RenderHandEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; -import org.lwjgl.opengl.GL11; +import static dan200.computercraft.client.render.ComputerBorderRenderer.*; import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_HEIGHT; import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_WIDTH; -import static dan200.computercraft.client.render.ComputerBorderRenderer.*; /** * Emulates map rendering for pocket computers. @@ -58,7 +54,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer } @Override - protected void renderItem( MatrixStack transform, IRenderTypeBuffer render, ItemStack stack ) + protected void renderItem( MatrixStack transform, IRenderTypeBuffer bufferSource, ItemStack stack, int light ) { ClientComputer computer = ItemPocketComputer.createClientComputer( stack ); Terminal terminal = computer == null ? null : computer.getTerminal(); @@ -95,61 +91,58 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer int frameColour = item.getColour( stack ); Matrix4f matrix = transform.last().pose(); - renderFrame( matrix, family, frameColour, width, height ); + renderFrame( matrix, bufferSource, family, frameColour, light, width, height ); // Render the light int lightColour = ItemPocketComputer.getLightState( stack ); if( lightColour == -1 ) lightColour = Colour.BLACK.getHex(); - renderLight( matrix, lightColour, width, height ); + renderLight( matrix, bufferSource, lightColour, width, height ); if( computer != null && terminal != null ) { - FixedWidthFontRenderer.drawTerminal( matrix, MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN ); + FixedWidthFontRenderer.drawTerminal( + matrix, bufferSource.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ), + MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN + ); + FixedWidthFontRenderer.drawBlocker( + matrix, bufferSource.getBuffer( RenderTypes.TERMINAL_BLOCKER ), + 0, 0, width, height + ); } else { - FixedWidthFontRenderer.drawEmptyTerminal( matrix, 0, 0, width, height ); + FixedWidthFontRenderer.drawEmptyTerminal( + matrix, bufferSource.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ), + 0, 0, width, height + ); } transform.popPose(); } - private static void renderFrame( Matrix4f transform, ComputerFamily family, int colour, int width, int height ) + private static void renderFrame( Matrix4f transform, IRenderTypeBuffer bufferSource, ComputerFamily family, int colour, int light, int width, int height ) { - RenderSystem.enableBlend(); - Minecraft.getInstance().getTextureManager() - .bind( colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family ) ); + ResourceLocation texture = colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family ); float r = ((colour >>> 16) & 0xFF) / 255.0f; float g = ((colour >>> 8) & 0xFF) / 255.0f; float b = (colour & 0xFF) / 255.0f; - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuilder(); - buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX ); - - ComputerBorderRenderer.render( transform, buffer, 0, 0, 0, width, height, true, r, g, b ); - - tessellator.end(); + ComputerBorderRenderer.render( transform, bufferSource.getBuffer( ComputerBorderRenderer.getRenderType( texture ) ), 0, 0, 0, light, width, height, true, r, g, b ); } - private static void renderLight( Matrix4f transform, int colour, int width, int height ) + private static void renderLight( Matrix4f transform, IRenderTypeBuffer bufferSource, int colour, int width, int height ) { - RenderSystem.disableTexture(); + byte r = (byte) ((colour >>> 16) & 0xFF); + byte g = (byte) ((colour >>> 8) & 0xFF); + byte b = (byte) (colour & 0xFF); + byte[] c = new byte[] { r, g, b, (byte) 255 }; - float r = ((colour >>> 16) & 0xFF) / 255.0f; - float g = ((colour >>> 8) & 0xFF) / 255.0f; - float b = (colour & 0xFF) / 255.0f; - - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuilder(); - buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR ); - buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex(); - buffer.vertex( transform, width, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex(); - buffer.vertex( transform, width, height + BORDER / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex(); - buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex(); - - tessellator.end(); - RenderSystem.enableTexture(); + IVertexBuilder buffer = bufferSource.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ); + FixedWidthFontRenderer.drawQuad( + transform, buffer, + width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0.001f, LIGHT_HEIGHT * 2, LIGHT_HEIGHT, + c, RenderTypes.FULL_BRIGHT_LIGHTMAP + ); } } diff --git a/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java index 212ed532f..17333c73c 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java @@ -18,9 +18,9 @@ import net.minecraftforge.client.event.RenderItemInFrameEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; +import static dan200.computercraft.client.render.PrintoutRenderer.*; import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_HEIGHT; import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_WIDTH; -import static dan200.computercraft.client.render.PrintoutRenderer.*; import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE; import static dan200.computercraft.shared.media.items.ItemPrintout.LINE_MAX_LENGTH; @@ -50,13 +50,13 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer } @Override - protected void renderItem( MatrixStack transform, IRenderTypeBuffer render, ItemStack stack ) + protected void renderItem( MatrixStack transform, IRenderTypeBuffer render, ItemStack stack, int light ) { transform.mulPose( Vector3f.XP.rotationDegrees( 180f ) ); transform.scale( 0.42f, 0.42f, -0.42f ); transform.translate( -0.5f, -0.48f, 0.0f ); - drawPrintout( transform, render, stack ); + drawPrintout( transform, render, stack, light ); } @SubscribeEvent @@ -74,10 +74,10 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer transform.scale( 0.95f, 0.95f, -0.95f ); transform.translate( -0.5f, -0.5f, 0.0f ); - drawPrintout( transform, event.getBuffers(), stack ); + drawPrintout( transform, event.getBuffers(), stack, event.getLight() ); } - private static void drawPrintout( MatrixStack transform, IRenderTypeBuffer render, ItemStack stack ) + private static void drawPrintout( MatrixStack transform, IRenderTypeBuffer render, ItemStack stack, int light ) { int pages = ItemPrintout.getPageCount( stack ); boolean book = ((ItemPrintout) stack.getItem()).getType() == ItemPrintout.Type.BOOK; @@ -105,9 +105,10 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer transform.translate( (max - width) / 2.0, (max - height) / 2.0, 0.0 ); Matrix4f matrix = transform.last().pose(); - drawBorder( matrix, render, 0, 0, -0.01f, 0, pages, book ); - drawText( matrix, render, - X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) + drawBorder( matrix, render, 0, 0, -0.01f, 0, pages, book, light ); + drawText( + matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, light, + ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) ); } } diff --git a/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java b/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java index 7de842c94..558dc9af6 100644 --- a/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java @@ -10,12 +10,8 @@ import dan200.computercraft.client.render.text.FixedWidthFontRenderer; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.util.Palette; import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.RenderState; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Matrix4f; -import org.lwjgl.opengl.GL11; import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_HEIGHT; import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE; @@ -60,37 +56,37 @@ public final class PrintoutRenderer private PrintoutRenderer() {} - public static void drawText( Matrix4f transform, IRenderTypeBuffer renderer, int x, int y, int start, TextBuffer[] text, TextBuffer[] colours ) + public static void drawText( Matrix4f transform, IRenderTypeBuffer renderer, int x, int y, int start, int light, TextBuffer[] text, TextBuffer[] colours ) { - IVertexBuilder buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); + IVertexBuilder buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT ); for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) { FixedWidthFontRenderer.drawString( transform, buffer, - x, y + line * FONT_HEIGHT, text[start + line], colours[start + line], null, Palette.DEFAULT, - false, 0, 0 + x, y + line * FONT_HEIGHT, text[start + line], colours[start + line], + Palette.DEFAULT, false, light ); } } - public static void drawText( Matrix4f transform, IRenderTypeBuffer renderer, int x, int y, int start, String[] text, String[] colours ) + public static void drawText( Matrix4f transform, IRenderTypeBuffer renderer, int x, int y, int start, int light, String[] text, String[] colours ) { - IVertexBuilder buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); + IVertexBuilder buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT ); for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) { FixedWidthFontRenderer.drawString( transform, buffer, x, y + line * FONT_HEIGHT, new TextBuffer( text[start + line] ), new TextBuffer( colours[start + line] ), - null, Palette.DEFAULT, false, 0, 0 + Palette.DEFAULT, false, light ); } } - public static void drawBorder( Matrix4f transform, IRenderTypeBuffer renderer, float x, float y, float z, int page, int pages, boolean isBook ) + public static void drawBorder( Matrix4f transform, IRenderTypeBuffer renderer, float x, float y, float z, int page, int pages, boolean isBook, int light ) { int leftPages = page; int rightPages = pages - page - 1; - IVertexBuilder buffer = renderer.getBuffer( Type.TYPE ); + IVertexBuilder buffer = renderer.getBuffer( RenderTypes.PRINTOUT_BACKGROUND ); if( isBook ) { @@ -100,86 +96,73 @@ public final class PrintoutRenderer float right = x + X_SIZE + offset - 4; // Left and right border - drawTexture( transform, buffer, left - 4, y - 8, z - 0.02f, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 ); - drawTexture( transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 ); + drawTexture( transform, buffer, left - 4, y - 8, z - 0.02f, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2, light ); + drawTexture( transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2, light ); // Draw centre panel (just stretched texture, sorry). drawTexture( transform, buffer, x - offset, y, z - 0.02f, X_SIZE + offset * 2, Y_SIZE, - COVER_X + COVER_SIZE / 2.0f, COVER_SIZE, COVER_SIZE, Y_SIZE + COVER_X + COVER_SIZE / 2.0f, COVER_SIZE, COVER_SIZE, Y_SIZE, light ); float borderX = left; while( borderX < right ) { double thisWidth = Math.min( right - borderX, X_SIZE ); - drawTexture( transform, buffer, borderX, y - 8, z - 0.02f, 0, COVER_Y, (float) thisWidth, COVER_SIZE ); - drawTexture( transform, buffer, borderX, y + Y_SIZE - 4, z - 0.02f, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE ); + drawTexture( transform, buffer, borderX, y - 8, z - 0.02f, 0, COVER_Y, (float) thisWidth, COVER_SIZE, light ); + drawTexture( transform, buffer, borderX, y + Y_SIZE - 4, z - 0.02f, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE, light ); borderX += thisWidth; } } // Left half - drawTexture( transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE ); + drawTexture( transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE, light ); for( int n = 0; n <= leftPages; n++ ) { drawTexture( transform, buffer, x - offsetAt( n ), y, z - 1e-3f * n, // Use the left "bold" fold for the outermost page n == leftPages ? 0 : X_FOLD_SIZE, 0, - X_FOLD_SIZE, Y_SIZE + X_FOLD_SIZE, Y_SIZE, light ); } // Right half - drawTexture( transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE ); + drawTexture( transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE, light ); for( int n = 0; n <= rightPages; n++ ) { drawTexture( transform, buffer, x + (X_SIZE - X_FOLD_SIZE) + offsetAt( n ), y, z - 1e-3f * n, // Two folds, then the main page. Use the right "bold" fold for the outermost page. X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0, - X_FOLD_SIZE, Y_SIZE + X_FOLD_SIZE, Y_SIZE, light ); } } - private static void drawTexture( Matrix4f matrix, IVertexBuilder buffer, float x, float y, float z, float u, float v, float width, float height ) + private static void drawTexture( Matrix4f matrix, IVertexBuilder buffer, float x, float y, float z, float u, float v, float width, float height, int light ) { - buffer.vertex( matrix, x, y + height, z ).uv( u / BG_SIZE, (v + height) / BG_SIZE ).endVertex(); - buffer.vertex( matrix, x + width, y + height, z ).uv( (u + width) / BG_SIZE, (v + height) / BG_SIZE ).endVertex(); - buffer.vertex( matrix, x + width, y, z ).uv( (u + width) / BG_SIZE, v / BG_SIZE ).endVertex(); - buffer.vertex( matrix, x, y, z ).uv( u / BG_SIZE, v / BG_SIZE ).endVertex(); + vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + height) / BG_SIZE, light ); + vertex( buffer, matrix, x + width, y + height, z, (u + width) / BG_SIZE, (v + height) / BG_SIZE, light ); + vertex( buffer, matrix, x + width, y, z, (u + width) / BG_SIZE, v / BG_SIZE, light ); + vertex( buffer, matrix, x, y, z, u / BG_SIZE, v / BG_SIZE, light ); } - private static void drawTexture( Matrix4f matrix, IVertexBuilder buffer, float x, float y, float z, float width, float height, float u, float v, float tWidth, float tHeight ) + private static void drawTexture( Matrix4f matrix, IVertexBuilder buffer, float x, float y, float z, float width, float height, float u, float v, float tWidth, float tHeight, int light ) { - buffer.vertex( matrix, x, y + height, z ).uv( u / BG_SIZE, (v + tHeight) / BG_SIZE ).endVertex(); - buffer.vertex( matrix, x + width, y + height, z ).uv( (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE ).endVertex(); - buffer.vertex( matrix, x + width, y, z ).uv( (u + tWidth) / BG_SIZE, v / BG_SIZE ).endVertex(); - buffer.vertex( matrix, x, y, z ).uv( u / BG_SIZE, v / BG_SIZE ).endVertex(); + vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + tHeight) / BG_SIZE, light ); + vertex( buffer, matrix, x + width, y + height, z, (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE, light ); + vertex( buffer, matrix, x + width, y, z, (u + tWidth) / BG_SIZE, v / BG_SIZE, light ); + vertex( buffer, matrix, x, y, z, u / BG_SIZE, v / BG_SIZE, light ); + } + + private static void vertex( IVertexBuilder buffer, Matrix4f matrix, float x, float y, float z, float u, float v, int light ) + { + buffer.vertex( matrix, x, y, z ).color( 255, 255, 255, 255 ).uv( u, v ).uv2( light ).endVertex(); } public static float offsetAt( int page ) { return (float) (32 * (1 - Math.pow( 1.2, -page ))); } - - private static final class Type extends RenderState - { - static final RenderType TYPE = RenderType.create( - "printout_background", DefaultVertexFormats.POSITION_TEX, GL11.GL_QUADS, 1024, - false, false, // useDelegate, needsSorting - RenderType.State.builder() - .setTextureState( new RenderState.TextureState( BG, false, false ) ) // blur, minimap - .setAlphaState( DEFAULT_ALPHA ) - .setLightmapState( NO_LIGHTMAP ) - .createCompositeState( false ) - ); - - private Type( String name, Runnable setup, Runnable destroy ) - { - super( name, setup, destroy ); - } - } } diff --git a/src/main/java/dan200/computercraft/client/render/RenderTypes.java b/src/main/java/dan200/computercraft/client/render/RenderTypes.java new file mode 100644 index 000000000..772f379f0 --- /dev/null +++ b/src/main/java/dan200/computercraft/client/render/RenderTypes.java @@ -0,0 +1,91 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ +package dan200.computercraft.client.render; + +import dan200.computercraft.client.render.text.FixedWidthFontRenderer; +import net.minecraft.client.renderer.RenderState; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + +public class RenderTypes +{ + public static final int FULL_BRIGHT_LIGHTMAP = (0xF << 4) | (0xF << 20); + + /** + * Renders a fullbright terminal without writing to the depth layer. This is used in combination with + * {@link #TERMINAL_BLOCKER} to ensure we can render a terminal without z-fighting. + */ + public static final RenderType TERMINAL_WITHOUT_DEPTH = Types.TERMINAL_WITHOUT_DEPTH; + + /** + * A transparent texture which only writes to the depth layer. + */ + public static final RenderType TERMINAL_BLOCKER = Types.TERMINAL_BLOCKER; + + /** + * Renders a fullbright terminal which also writes to the depth layer. This is used when z-fighting isn't an issue - + * for instance rendering an empty terminal or inside a GUI. + * + * This is identical to vanilla's {@link RenderType#text}. Forge overrides one with a definition which sets + * sortOnUpload to true, which is entirely broken! + */ + public static final RenderType TERMINAL_WITH_DEPTH = Types.TERMINAL_WITH_DEPTH; + + /** + * A variant of {@link #TERMINAL_WITH_DEPTH} which uses the lightmap rather than rendering fullbright. + */ + public static final RenderType PRINTOUT_TEXT = RenderType.text( FixedWidthFontRenderer.FONT ); + + /** + * Printout's background texture. {@link RenderType#text(ResourceLocation)} is a little questionable, but + * it is what maps use, so should behave the same as vanilla in both item frames and in-hand. + */ + public static final RenderType PRINTOUT_BACKGROUND = RenderType.text( new ResourceLocation( "computercraft", "textures/gui/printout.png" ) ); + + private static final class Types extends RenderState + { + private static final RenderState.TextureState TERM_FONT_TEXTURE = new RenderState.TextureState( + FixedWidthFontRenderer.FONT, + false, false // blur, minimap + ); + private static final VertexFormat TERM_FORMAT = DefaultVertexFormats.POSITION_COLOR_TEX; + + static final RenderType TERMINAL_WITHOUT_DEPTH = RenderType.create( + "terminal_without_depth", TERM_FORMAT, GL11.GL_QUADS, 1024, + false, false, // useDelegate, needsSorting + RenderType.State.builder() + .setTextureState( TERM_FONT_TEXTURE ) + .setAlphaState( DEFAULT_ALPHA ) + .setWriteMaskState( COLOR_WRITE ) + .createCompositeState( false ) + ); + + static final RenderType TERMINAL_BLOCKER = RenderType.create( + "terminal_blocker", DefaultVertexFormats.POSITION, GL11.GL_QUADS, 256, + false, false, // useDelegate, needsSorting + RenderType.State.builder() + .setWriteMaskState( DEPTH_WRITE ) + .createCompositeState( false ) + ); + + static final RenderType TERMINAL_WITH_DEPTH = RenderType.create( + "terminal_with_depth", TERM_FORMAT, GL11.GL_QUADS, 1024, + false, false, // useDelegate, needsSorting + RenderType.State.builder() + .setTextureState( TERM_FONT_TEXTURE ) + .setAlphaState( DEFAULT_ALPHA ) + .createCompositeState( false ) + ); + + private Types( String name, Runnable setup, Runnable destroy ) + { + super( name, setup, destroy ); + } + } +} diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java index c6b4dd3c4..2dbf002d5 100644 --- a/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java @@ -118,8 +118,8 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer // Sneaky hack here: we get a buffer now in order to flush existing ones and set up the appropriate // render state. I've no clue how well this'll work in future versions of Minecraft, but it does the trick // for now. - IVertexBuilder buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); - FixedWidthFontRenderer.TYPE.setupRenderState(); + IVertexBuilder buffer = renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ); + RenderTypes.TERMINAL_WITHOUT_DEPTH.setupRenderState(); renderTerminal( matrix, originTerminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale) ); @@ -132,14 +132,14 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer else { FixedWidthFontRenderer.drawEmptyTerminal( - transform.last().pose(), renderer, + transform.last().pose(), renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ), -MARGIN, MARGIN, (float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2) ); } FixedWidthFontRenderer.drawBlocker( - transform.last().pose(), renderer, + transform.last().pose(), renderer.getBuffer( RenderTypes.TERMINAL_BLOCKER ), -MARGIN, MARGIN, (float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2) ); @@ -222,7 +222,7 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer { Tessellator tessellator = Tessellator.getInstance(); BufferBuilder builder = tessellator.getBuilder(); - builder.begin( FixedWidthFontRenderer.TYPE.mode(), FixedWidthFontRenderer.TYPE.format() ); + builder.begin( RenderTypes.TERMINAL_WITHOUT_DEPTH.mode(), RenderTypes.TERMINAL_WITHOUT_DEPTH.format() ); FixedWidthFontRenderer.drawTerminalWithoutCursor( IDENTITY, builder, 0, 0, terminal, !monitor.isColour(), yMargin, yMargin, xMargin, xMargin @@ -233,10 +233,10 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer } vbo.bind(); - FixedWidthFontRenderer.TYPE.format().setupBufferState( 0L ); - vbo.draw( matrix, FixedWidthFontRenderer.TYPE.mode() ); + RenderTypes.TERMINAL_WITHOUT_DEPTH.format().setupBufferState( 0L ); + vbo.draw( matrix, RenderTypes.TERMINAL_WITHOUT_DEPTH.mode() ); VertexBuffer.unbind(); - FixedWidthFontRenderer.TYPE.format().clearBufferState(); + RenderTypes.TERMINAL_WITHOUT_DEPTH.format().clearBufferState(); break; } } diff --git a/src/main/java/dan200/computercraft/client/render/text/FixedWidthFontRenderer.java b/src/main/java/dan200/computercraft/client/render/text/FixedWidthFontRenderer.java index 78e4ecab3..08137cd73 100644 --- a/src/main/java/dan200/computercraft/client/render/text/FixedWidthFontRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/text/FixedWidthFontRenderer.java @@ -5,46 +5,57 @@ */ package dan200.computercraft.client.render.text; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.IVertexBuilder; import dan200.computercraft.client.FrameInfo; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.Palette; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.RenderState; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.client.renderer.vertex.VertexFormat; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.util.math.vector.TransformationMatrix; -import org.lwjgl.opengl.GL11; import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP; + +/** + * Handles rendering fixed width text and computer terminals. + * + * This class has several modes of usage: + *
    + *
  • {@link #drawString}: Drawing basic text without a terminal (such as for printouts). Unlike the other methods, + * this accepts a lightmap coordinate as, unlike terminals, printed pages render fullbright.
  • + *
  • {@link #drawTerminalWithoutCursor}/{@link #drawCursor}: Draw a terminal without a cursor and then draw the cursor + * separately. This is used by the monitor renderer to render the terminal to a VBO and draw the cursor dynamically. + *
  • + *
  • {@link #drawTerminal}: Draw a terminal with a cursor. This is used by the various computer GUIs to render the + * whole term.
  • + *
  • {@link #drawBlocker}: When rendering a terminal using {@link dan200.computercraft.client.render.RenderTypes#TERMINAL_WITHOUT_DEPTH} you need to + * render an additional "depth blocker" on top of the monitor.
  • + *
+ */ public final class FixedWidthFontRenderer { - private static final Matrix4f IDENTITY = TransformationMatrix.identity().getMatrix(); - - private static final ResourceLocation FONT = new ResourceLocation( "computercraft", "textures/gui/term_font.png" ); + public static final ResourceLocation FONT = new ResourceLocation( "computercraft", "textures/gui/term_font.png" ); public static final int FONT_HEIGHT = 9; public static final int FONT_WIDTH = 6; public static final float WIDTH = 256.0f; - public static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH; - public static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH; + private static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH; + private static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH; - public static final RenderType TYPE = Type.MAIN; + private static final byte[] BLACK = new byte[] { byteColour( Colour.BLACK.getR() ), byteColour( Colour.BLACK.getR() ), byteColour( Colour.BLACK.getR() ), (byte) 255 }; private FixedWidthFontRenderer() { } + private static byte byteColour( float c ) + { + return (byte) (int) (c * 255); + } + public static float toGreyscale( double[] rgb ) { return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3); @@ -55,7 +66,7 @@ public final class FixedWidthFontRenderer return 15 - Terminal.getColour( c, def ); } - private static void drawChar( Matrix4f transform, IVertexBuilder buffer, float x, float y, int index, float r, float g, float b ) + private static void drawChar( Matrix4f transform, IVertexBuilder buffer, float x, float y, int index, byte[] colour, int light ) { // Short circuit to avoid the common case - the texture should be blank here after all. if( index == '\0' || index == ' ' ) return; @@ -66,56 +77,37 @@ public final class FixedWidthFontRenderer int xStart = 1 + column * (FONT_WIDTH + 2); int yStart = 1 + row * (FONT_HEIGHT + 2); - buffer.vertex( transform, x, y, 0f ).color( r, g, b, 1.0f ).uv( xStart / WIDTH, yStart / WIDTH ).endVertex(); - buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).uv( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).endVertex(); - buffer.vertex( transform, x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).uv( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).endVertex(); - buffer.vertex( transform, x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).uv( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).endVertex(); - buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).uv( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).endVertex(); - buffer.vertex( transform, x + FONT_WIDTH, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).uv( (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).endVertex(); + quad( + transform, buffer, x, y, x + FONT_WIDTH, y + FONT_HEIGHT, 0, colour, + xStart / WIDTH, yStart / WIDTH, (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH, light + ); } - private static void drawQuad( Matrix4f transform, IVertexBuilder buffer, float x, float y, float width, float height, float r, float g, float b ) + public static void drawQuad( Matrix4f transform, IVertexBuilder buffer, float x, float y, float z, float width, float height, byte[] colour, int light ) { - buffer.vertex( transform, x, y, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_START ).endVertex(); - buffer.vertex( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_END ).endVertex(); - buffer.vertex( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_START ).endVertex(); - buffer.vertex( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_START ).endVertex(); - buffer.vertex( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_END ).endVertex(); - buffer.vertex( transform, x + width, y + height, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_END ).endVertex(); + quad( transform, buffer, x, y, x + width, y + height, z, colour, BACKGROUND_START, BACKGROUND_START, BACKGROUND_END, BACKGROUND_END, light ); } - private static void drawQuad( Matrix4f transform, IVertexBuilder buffer, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex ) + private static void drawQuad( Matrix4f transform, IVertexBuilder buffer, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex, int light ) { - double[] colour = palette.getColour( getColour( colourIndex, Colour.BLACK ) ); - float r, g, b; - if( greyscale ) - { - r = g = b = toGreyscale( colour ); - } - else - { - r = (float) colour[0]; - g = (float) colour[1]; - b = (float) colour[2]; - } - - drawQuad( transform, buffer, x, y, width, height, r, g, b ); + byte[] colour = palette.getByteColour( getColour( colourIndex, Colour.BLACK ), greyscale ); + drawQuad( transform, buffer, x, y, 0, width, height, colour, light ); } private static void drawBackground( - @Nonnull Matrix4f transform, @Nonnull IVertexBuilder renderer, float x, float y, + @Nonnull Matrix4f transform, @Nonnull IVertexBuilder buffer, float x, float y, @Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, - float leftMarginSize, float rightMarginSize, float height + float leftMarginSize, float rightMarginSize, float height, int light ) { if( leftMarginSize > 0 ) { - drawQuad( transform, renderer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) ); + drawQuad( transform, buffer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ), light ); } if( rightMarginSize > 0 ) { - drawQuad( transform, renderer, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, greyscale, backgroundColour.charAt( backgroundColour.length() - 1 ) ); + drawQuad( transform, buffer, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, greyscale, backgroundColour.charAt( backgroundColour.length() - 1 ), light ); } // Batch together runs of identical background cells. @@ -128,7 +120,7 @@ public final class FixedWidthFontRenderer if( blockColour != '\0' ) { - drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour ); + drawQuad( transform, buffer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour, light ); } blockColour = colourIndex; @@ -137,42 +129,23 @@ public final class FixedWidthFontRenderer if( blockColour != '\0' ) { - drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, greyscale, blockColour ); + drawQuad( transform, buffer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, greyscale, blockColour, light ); } } public static void drawString( @Nonnull Matrix4f transform, @Nonnull IVertexBuilder renderer, float x, float y, - @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, - @Nonnull Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize + @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nonnull Palette palette, boolean greyscale, int light ) { - if( backgroundColour != null ) - { - drawBackground( transform, renderer, x, y, backgroundColour, palette, greyscale, leftMarginSize, rightMarginSize, FONT_HEIGHT ); - } - for( int i = 0; i < text.length(); i++ ) { - double[] colour = palette.getColour( getColour( textColour.charAt( i ), Colour.BLACK ) ); - float r, g, b; - if( greyscale ) - { - r = g = b = toGreyscale( colour ); - } - else - { - r = (float) colour[0]; - g = (float) colour[1]; - b = (float) colour[2]; - } + byte[] colour = palette.getByteColour( getColour( textColour.charAt( i ), Colour.BLACK ), greyscale ); - // Draw char int index = text.charAt( i ); if( index > 255 ) index = '?'; - drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b ); + drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, colour, light ); } - } public static void drawTerminalWithoutCursor( @@ -188,53 +161,49 @@ public final class FixedWidthFontRenderer drawBackground( transform, buffer, x, y - topMarginSize, terminal.getBackgroundColourLine( 0 ), palette, greyscale, - leftMarginSize, rightMarginSize, topMarginSize + leftMarginSize, rightMarginSize, topMarginSize, FULL_BRIGHT_LIGHTMAP ); drawBackground( transform, buffer, x, y + height * FONT_HEIGHT, terminal.getBackgroundColourLine( height - 1 ), palette, greyscale, - leftMarginSize, rightMarginSize, bottomMarginSize + leftMarginSize, rightMarginSize, bottomMarginSize, FULL_BRIGHT_LIGHTMAP ); // The main text for( int i = 0; i < height; i++ ) { + float rowY = y + FONT_HEIGHT * i; + drawBackground( + transform, buffer, x, rowY, terminal.getBackgroundColourLine( i ), + palette, greyscale, leftMarginSize, rightMarginSize, FONT_HEIGHT, FULL_BRIGHT_LIGHTMAP + ); + drawString( - transform, buffer, x, y + FixedWidthFontRenderer.FONT_HEIGHT * i, - terminal.getLine( i ), terminal.getTextColourLine( i ), terminal.getBackgroundColourLine( i ), - palette, greyscale, leftMarginSize, rightMarginSize + transform, buffer, x, rowY, terminal.getLine( i ), terminal.getTextColourLine( i ), + palette, greyscale, FULL_BRIGHT_LIGHTMAP ); } } + public static boolean isCursorVisible( Terminal terminal ) + { + if( !terminal.getCursorBlink() ) return false; + + int cursorX = terminal.getCursorX(); + int cursorY = terminal.getCursorY(); + return cursorX >= 0 && cursorX < terminal.getWidth() && cursorY >= 0 && cursorY < terminal.getHeight(); + } + public static void drawCursor( @Nonnull Matrix4f transform, @Nonnull IVertexBuilder buffer, float x, float y, @Nonnull Terminal terminal, boolean greyscale ) { - Palette palette = terminal.getPalette(); - int width = terminal.getWidth(); - int height = terminal.getHeight(); - - int cursorX = terminal.getCursorX(); - int cursorY = terminal.getCursorY(); - if( terminal.getCursorBlink() && cursorX >= 0 && cursorX < width && cursorY >= 0 && cursorY < height && FrameInfo.getGlobalCursorBlink() ) + if( isCursorVisible( terminal ) && FrameInfo.getGlobalCursorBlink() ) { - double[] colour = palette.getColour( 15 - terminal.getTextColour() ); - float r, g, b; - if( greyscale ) - { - r = g = b = toGreyscale( colour ); - } - else - { - r = (float) colour[0]; - g = (float) colour[1]; - b = (float) colour[2]; - } - - drawChar( transform, buffer, x + cursorX * FONT_WIDTH, y + cursorY * FONT_HEIGHT, '_', r, g, b ); + byte[] colour = terminal.getPalette().getByteColour( 15 - terminal.getTextColour(), greyscale ); + drawChar( transform, buffer, x + terminal.getCursorX() * FONT_WIDTH, y + terminal.getCursorY() * FONT_HEIGHT, '_', colour, FULL_BRIGHT_LIGHTMAP ); } } @@ -248,82 +217,23 @@ public final class FixedWidthFontRenderer drawCursor( transform, buffer, x, y, terminal, greyscale ); } - public static void drawTerminal( - @Nonnull Matrix4f transform, float x, float y, @Nonnull Terminal terminal, boolean greyscale, - float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize - ) + public static void drawEmptyTerminal( @Nonnull Matrix4f transform, @Nonnull IVertexBuilder renderer, float x, float y, float width, float height ) { - bindFont(); - - IRenderTypeBuffer.Impl renderer = Minecraft.getInstance().renderBuffers().bufferSource(); - IVertexBuilder buffer = renderer.getBuffer( TYPE ); - drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); - renderer.endBatch( TYPE ); + drawQuad( transform, renderer, x, y, 0, width, height, BLACK, FULL_BRIGHT_LIGHTMAP ); } - public static void drawEmptyTerminal( @Nonnull Matrix4f transform, @Nonnull IRenderTypeBuffer renderer, float x, float y, float width, float height ) + public static void drawBlocker( @Nonnull Matrix4f transform, @Nonnull IVertexBuilder buffer, float x, float y, float width, float height ) { - Colour colour = Colour.BLACK; - drawQuad( transform, renderer.getBuffer( TYPE ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); + drawQuad( transform, buffer, x, y, 0, width, height, BLACK, FULL_BRIGHT_LIGHTMAP ); } - public static void drawEmptyTerminal( @Nonnull Matrix4f transform, float x, float y, float width, float height ) + private static void quad( Matrix4f matrix, IVertexBuilder buffer, float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2, int light ) { - bindFont(); + byte r = rgba[0], g = rgba[1], b = rgba[2], a = rgba[3]; - IRenderTypeBuffer.Impl renderer = Minecraft.getInstance().renderBuffers().bufferSource(); - drawEmptyTerminal( transform, renderer, x, y, width, height ); - renderer.endBatch(); - } - - public static void drawEmptyTerminal( float x, float y, float width, float height ) - { - drawEmptyTerminal( IDENTITY, x, y, width, height ); - } - - public static void drawBlocker( @Nonnull Matrix4f transform, @Nonnull IRenderTypeBuffer renderer, float x, float y, float width, float height ) - { - Colour colour = Colour.BLACK; - drawQuad( transform, renderer.getBuffer( Type.BLOCKER ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); - } - - private static void bindFont() - { - Minecraft.getInstance().getTextureManager().bind( FONT ); - RenderSystem.texParameter( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP ); - } - - private static final class Type extends RenderState - { - private static final int GL_MODE = GL11.GL_TRIANGLES; - - private static final VertexFormat FORMAT = DefaultVertexFormats.POSITION_COLOR_TEX; - - static final RenderType MAIN = RenderType.create( - "terminal_font", FORMAT, GL_MODE, 1024, - false, false, // useDelegate, needsSorting - RenderType.State.builder() - .setTextureState( new RenderState.TextureState( FONT, false, false ) ) // blur, minimap - .setAlphaState( DEFAULT_ALPHA ) - .setLightmapState( NO_LIGHTMAP ) - .setWriteMaskState( COLOR_WRITE ) - .createCompositeState( false ) - ); - - static final RenderType BLOCKER = RenderType.create( - "terminal_blocker", FORMAT, GL_MODE, 256, - false, false, // useDelegate, needsSorting - RenderType.State.builder() - .setTextureState( new RenderState.TextureState( FONT, false, false ) ) // blur, minimap - .setAlphaState( DEFAULT_ALPHA ) - .setWriteMaskState( DEPTH_WRITE ) - .setLightmapState( NO_LIGHTMAP ) - .createCompositeState( false ) - ); - - private Type( String name, Runnable setup, Runnable destroy ) - { - super( name, setup, destroy ); - } + buffer.vertex( matrix, x1, y1, z ).color( r, g, b, a ).uv( u1, v1 ).uv2( light ).endVertex(); + buffer.vertex( matrix, x1, y2, z ).color( r, g, b, a ).uv( u1, v2 ).uv2( light ).endVertex(); + buffer.vertex( matrix, x2, y2, z ).color( r, g, b, a ).uv( u2, v2 ).uv2( light ).endVertex(); + buffer.vertex( matrix, x2, y1, z ).color( r, g, b, a ).uv( u2, v1 ).uv2( light ).endVertex(); } } diff --git a/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java b/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java index 5fa141a1f..aaff61ce9 100644 --- a/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java +++ b/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java @@ -14,8 +14,8 @@ import dan200.computercraft.core.computer.TimeoutState; import dan200.computercraft.core.tracking.Tracking; import dan200.computercraft.core.tracking.TrackingField; import dan200.computercraft.shared.util.ThreadUtils; -import org.squiddev.cobalt.*; import org.squiddev.cobalt.LuaTable; +import org.squiddev.cobalt.*; import org.squiddev.cobalt.compiler.CompileException; import org.squiddev.cobalt.compiler.LoadState; import org.squiddev.cobalt.debug.DebugFrame; diff --git a/src/main/java/dan200/computercraft/core/tracking/ComputerMBean.java b/src/main/java/dan200/computercraft/core/tracking/ComputerMBean.java index a76471a34..8d1fe8acc 100644 --- a/src/main/java/dan200/computercraft/core/tracking/ComputerMBean.java +++ b/src/main/java/dan200/computercraft/core/tracking/ComputerMBean.java @@ -57,7 +57,8 @@ public final class ComputerMBean implements DynamicMBean, Tracker { ManagementFactory.getPlatformMBeanServer().registerMBean( instance = new ComputerMBean(), new ObjectName( "dan200.computercraft:type=Computers" ) ); } - catch( InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException | MalformedObjectNameException e ) + catch( InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException | + MalformedObjectNameException e ) { ComputerCraft.log.warn( "Failed to register JMX bean", e ); } diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java index 8f569fbed..d7e21dfdb 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java @@ -54,7 +54,7 @@ public abstract class BlockComputerBase extends Bloc super.onPlace( state, world, pos, oldState, isMoving ); TileEntity tile = world.getBlockEntity( pos ); - if( tile instanceof TileComputerBase ) ((TileComputerBase) tile).updateInputsImmediately( ); + if( tile instanceof TileComputerBase ) ((TileComputerBase) tile).updateInputsImmediately(); } @Override diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java index ff19f716d..7d126cded 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java @@ -7,7 +7,7 @@ package dan200.computercraft.shared.peripheral.monitor; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.client.render.text.FixedWidthFontRenderer; +import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.shared.common.ClientTerminal; import net.minecraft.client.renderer.vertex.VertexBuffer; import net.minecraft.util.math.BlockPos; @@ -82,7 +82,7 @@ public final class ClientMonitor extends ClientTerminal if( buffer != null ) return false; deleteBuffers(); - buffer = new VertexBuffer( FixedWidthFontRenderer.TYPE.format() ); + buffer = new VertexBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH.format() ); addMonitor(); return true; diff --git a/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java index d3d4be2f9..3fdec3c02 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java +++ b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java @@ -69,6 +69,7 @@ import java.util.Optional; * accessible by accessing the `"left"` or `"right"` peripheral. * * [Turtle Graphics]: https://en.wikipedia.org/wiki/Turtle_graphics "Turtle graphics" + * * @cc.module turtle * @cc.since 1.3 */ diff --git a/src/main/java/dan200/computercraft/shared/util/Palette.java b/src/main/java/dan200/computercraft/shared/util/Palette.java index 55e3dcd08..c176ba525 100644 --- a/src/main/java/dan200/computercraft/shared/util/Palette.java +++ b/src/main/java/dan200/computercraft/shared/util/Palette.java @@ -5,13 +5,18 @@ */ package dan200.computercraft.shared.util; +import dan200.computercraft.client.render.text.FixedWidthFontRenderer; import net.minecraft.nbt.CompoundNBT; import net.minecraft.network.PacketBuffer; +import javax.annotation.Nonnull; + public class Palette { private static final int PALETTE_SIZE = 16; private final double[][] colours = new double[PALETTE_SIZE][3]; + private final byte[][] byteColours = new byte[PALETTE_SIZE][4]; + private final byte[][] greyByteColours = new byte[PALETTE_SIZE][4]; public static final Palette DEFAULT = new Palette(); @@ -19,16 +24,23 @@ public class Palette { // Get the default palette resetColours(); + + for( int i = 0; i < PALETTE_SIZE; i++ ) byteColours[i][3] = greyByteColours[i][3] = (byte) 255; } public void setColour( int i, double r, double g, double b ) { - if( i >= 0 && i < colours.length ) - { - colours[i][0] = r; - colours[i][1] = g; - colours[i][2] = b; - } + if( i < 0 || i >= colours.length ) return; + colours[i][0] = r; + colours[i][1] = g; + colours[i][2] = b; + + byteColours[i][0] = (byte) (int) (r * 255); + byteColours[i][1] = (byte) (int) (g * 255); + byteColours[i][2] = (byte) (int) (b * 255); + + byte grey = (byte) (int) ((r + g + b) / 3 * 255); + greyByteColours[i][0] = greyByteColours[i][1] = greyByteColours[i][2] = grey; } public void setColour( int i, Colour colour ) @@ -38,19 +50,29 @@ public class Palette public double[] getColour( int i ) { - if( i >= 0 && i < colours.length ) - { - return colours[i]; - } - return null; + return i >= 0 && i < colours.length ? colours[i] : null; + } + + /** + * Get the colour as a set of bytes rather than floats. This is called frequently by {@link FixedWidthFontRenderer}, + * as our vertex format uses bytes. + * + * This allows us to do the conversion once (when setting the colour) rather than for every vertex, at the cost of + * some memory overhead. + * + * @param i The colour index. + * @param greyscale Whether this number should be converted to greyscale. + * @return The number as a tuple of bytes. + */ + @Nonnull + public byte[] getByteColour( int i, boolean greyscale ) + { + return greyscale ? greyByteColours[i] : byteColours[i]; } public void resetColour( int i ) { - if( i >= 0 && i < colours.length ) - { - setColour( i, Colour.VALUES[i] ); - } + if( i >= 0 && i < colours.length ) setColour( i, Colour.VALUES[i] ); } public void resetColours() @@ -89,9 +111,12 @@ public class Palette public void read( PacketBuffer buffer ) { - for( double[] colour : colours ) + for( int i = 0; i < PALETTE_SIZE; i++ ) { - for( int i = 0; i < colour.length; i++ ) colour[i] = (buffer.readByte() & 0xFF) / 255.0; + double r = (buffer.readByte() & 0xFF) / 255.0; + double g = (buffer.readByte() & 0xFF) / 255.0; + double b = (buffer.readByte() & 0xFF) / 255.0; + setColour( i, r, g, b ); } } @@ -117,7 +142,8 @@ public class Palette for( int i = 0; i < colours.length; i++ ) { - colours[i] = decodeRGB8( rgb8[i] ); + double[] colours = decodeRGB8( rgb8[i] ); + setColour( i, colours[0], colours[1], colours[2] ); } } }