mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 05:33:00 +00:00 
			
		
		
		
	Merge branch 'mc-1.18.x' into mc-1.19.x
This commit is contained in:
		| @@ -152,6 +152,7 @@ dependencies { | |||||||
|     extraModsCompileOnly fg.deobf("mezz.jei:jei-1.19-forge-api:11.1.1.236") |     extraModsCompileOnly fg.deobf("mezz.jei:jei-1.19-forge-api:11.1.1.236") | ||||||
|     extraModsCompileOnly fg.deobf("mezz.jei:jei-1.19-common-api:11.1.1.236") |     extraModsCompileOnly fg.deobf("mezz.jei:jei-1.19-common-api:11.1.1.236") | ||||||
|     extraModsRuntimeOnly fg.deobf("mezz.jei:jei-1.19-forge:11.1.1.236") |     extraModsRuntimeOnly fg.deobf("mezz.jei:jei-1.19-forge:11.1.1.236") | ||||||
|  |     extraModsCompileOnly fg.deobf("maven.modrinth:oculus:1.2.5") | ||||||
| 
 | 
 | ||||||
|     shade 'org.squiddev:Cobalt:0.5.5' |     shade 'org.squiddev:Cobalt:0.5.5' | ||||||
|     shade 'io.netty:netty-codec-http:4.1.76.Final' |     shade 'io.netty:netty-codec-http:4.1.76.Final' | ||||||
|   | |||||||
| @@ -8,7 +8,6 @@ package dan200.computercraft.client.gui; | |||||||
| import com.mojang.blaze3d.systems.RenderSystem; | import com.mojang.blaze3d.systems.RenderSystem; | ||||||
| import com.mojang.blaze3d.vertex.PoseStack; | import com.mojang.blaze3d.vertex.PoseStack; | ||||||
| import com.mojang.blaze3d.vertex.Tesselator; | import com.mojang.blaze3d.vertex.Tesselator; | ||||||
| import com.mojang.math.Matrix4f; |  | ||||||
| import dan200.computercraft.core.terminal.TextBuffer; | import dan200.computercraft.core.terminal.TextBuffer; | ||||||
| import dan200.computercraft.shared.common.ContainerHeldItem; | import dan200.computercraft.shared.common.ContainerHeldItem; | ||||||
| import dan200.computercraft.shared.media.items.ItemPrintout; | import dan200.computercraft.shared.media.items.ItemPrintout; | ||||||
| @@ -99,9 +98,8 @@ public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem> | |||||||
|         RenderSystem.enableDepthTest(); |         RenderSystem.enableDepthTest(); | ||||||
| 
 | 
 | ||||||
|         MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() ); |         MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() ); | ||||||
|         Matrix4f matrix = transform.last().pose(); |         drawBorder( transform, renderer, leftPos, topPos, getBlitOffset(), page, pages, book, FULL_BRIGHT_LIGHTMAP ); | ||||||
|         drawBorder( matrix, renderer, leftPos, topPos, getBlitOffset(), page, pages, book, FULL_BRIGHT_LIGHTMAP ); |         drawText( transform, renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours ); | ||||||
|         drawText( matrix, renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours ); |  | ||||||
|         renderer.endBatch(); |         renderer.endBatch(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -7,7 +7,6 @@ package dan200.computercraft.client.gui.widgets; | |||||||
| 
 | 
 | ||||||
| import com.mojang.blaze3d.vertex.PoseStack; | import com.mojang.blaze3d.vertex.PoseStack; | ||||||
| import com.mojang.blaze3d.vertex.Tesselator; | import com.mojang.blaze3d.vertex.Tesselator; | ||||||
| import com.mojang.math.Matrix4f; |  | ||||||
| import dan200.computercraft.client.render.RenderTypes; | import dan200.computercraft.client.render.RenderTypes; | ||||||
| import dan200.computercraft.client.render.text.FixedWidthFontRenderer; | import dan200.computercraft.client.render.text.FixedWidthFontRenderer; | ||||||
| import dan200.computercraft.core.terminal.Terminal; | import dan200.computercraft.core.terminal.Terminal; | ||||||
| @@ -316,11 +315,10 @@ public class WidgetTerminal extends AbstractWidget | |||||||
|     public void render( @Nonnull PoseStack transform, int mouseX, int mouseY, float partialTicks ) |     public void render( @Nonnull PoseStack transform, int mouseX, int mouseY, float partialTicks ) | ||||||
|     { |     { | ||||||
|         if( !visible ) return; |         if( !visible ) return; | ||||||
|         Matrix4f matrix = transform.last().pose(); |  | ||||||
|         Terminal terminal = computer.getTerminal(); |         Terminal terminal = computer.getTerminal(); | ||||||
| 
 | 
 | ||||||
|         var bufferSource = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() ); |         var bufferSource = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() ); | ||||||
|         var emitter = FixedWidthFontRenderer.toVertexConsumer( matrix, bufferSource.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ) ); |         var emitter = FixedWidthFontRenderer.toVertexConsumer( transform, bufferSource.getBuffer( RenderTypes.TERMINAL ) ); | ||||||
| 
 | 
 | ||||||
|         if( terminal != null ) |         if( terminal != null ) | ||||||
|         { |         { | ||||||
|   | |||||||
| @@ -96,23 +96,19 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer | |||||||
|         // Render the light |         // Render the light | ||||||
|         int lightColour = ItemPocketComputer.getLightState( stack ); |         int lightColour = ItemPocketComputer.getLightState( stack ); | ||||||
|         if( lightColour == -1 ) lightColour = Colour.BLACK.getHex(); |         if( lightColour == -1 ) lightColour = Colour.BLACK.getHex(); | ||||||
|         renderLight( matrix, bufferSource, lightColour, width, height ); |         renderLight( transform, bufferSource, lightColour, width, height ); | ||||||
| 
 | 
 | ||||||
|         if( computer != null && terminal != null ) |         if( computer != null && terminal != null ) | ||||||
|         { |         { | ||||||
|             FixedWidthFontRenderer.drawTerminal( |             FixedWidthFontRenderer.drawTerminal( | ||||||
|                 FixedWidthFontRenderer.toVertexConsumer( matrix, bufferSource.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ) ), |                 FixedWidthFontRenderer.toVertexConsumer( transform, bufferSource.getBuffer( RenderTypes.TERMINAL ) ), | ||||||
|                 MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN |                 MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN | ||||||
|             ); |             ); | ||||||
|             FixedWidthFontRenderer.drawBlocker( |  | ||||||
|                 FixedWidthFontRenderer.toVertexConsumer( matrix, bufferSource.getBuffer( RenderTypes.TERMINAL_BLOCKER ) ), |  | ||||||
|                 0, 0, width, height |  | ||||||
|             ); |  | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             FixedWidthFontRenderer.drawEmptyTerminal( |             FixedWidthFontRenderer.drawEmptyTerminal( | ||||||
|                 FixedWidthFontRenderer.toVertexConsumer( matrix, bufferSource.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ) ), |                 FixedWidthFontRenderer.toVertexConsumer( transform, bufferSource.getBuffer( RenderTypes.TERMINAL ) ), | ||||||
|                 0, 0, width, height |                 0, 0, width, height | ||||||
|             ); |             ); | ||||||
|         } |         } | ||||||
| @@ -131,14 +127,14 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer | |||||||
|         ComputerBorderRenderer.render( transform, render.getBuffer( ComputerBorderRenderer.getRenderType( texture ) ), 0, 0, 0, light, width, height, true, r, g, b ); |         ComputerBorderRenderer.render( transform, render.getBuffer( ComputerBorderRenderer.getRenderType( texture ) ), 0, 0, 0, light, width, height, true, r, g, b ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static void renderLight( Matrix4f transform, MultiBufferSource render, int colour, int width, int height ) |     private static void renderLight( PoseStack transform, MultiBufferSource render, int colour, int width, int height ) | ||||||
|     { |     { | ||||||
|         byte r = (byte) ((colour >>> 16) & 0xFF); |         byte r = (byte) ((colour >>> 16) & 0xFF); | ||||||
|         byte g = (byte) ((colour >>> 8) & 0xFF); |         byte g = (byte) ((colour >>> 8) & 0xFF); | ||||||
|         byte b = (byte) (colour & 0xFF); |         byte b = (byte) (colour & 0xFF); | ||||||
|         byte[] c = new byte[] { r, g, b, (byte) 255 }; |         byte[] c = new byte[] { r, g, b, (byte) 255 }; | ||||||
| 
 | 
 | ||||||
|         VertexConsumer buffer = render.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ); |         VertexConsumer buffer = render.getBuffer( RenderTypes.TERMINAL ); | ||||||
|         FixedWidthFontRenderer.drawQuad( |         FixedWidthFontRenderer.drawQuad( | ||||||
|             FixedWidthFontRenderer.toVertexConsumer( transform, buffer ), |             FixedWidthFontRenderer.toVertexConsumer( transform, buffer ), | ||||||
|             width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0.001f, LIGHT_HEIGHT * 2, LIGHT_HEIGHT, |             width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0.001f, LIGHT_HEIGHT * 2, LIGHT_HEIGHT, | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ | |||||||
| package dan200.computercraft.client.render; | package dan200.computercraft.client.render; | ||||||
| 
 | 
 | ||||||
| import com.mojang.blaze3d.vertex.PoseStack; | import com.mojang.blaze3d.vertex.PoseStack; | ||||||
| import com.mojang.math.Matrix4f; |  | ||||||
| import com.mojang.math.Vector3f; | import com.mojang.math.Vector3f; | ||||||
| import dan200.computercraft.ComputerCraft; | import dan200.computercraft.ComputerCraft; | ||||||
| import dan200.computercraft.shared.media.items.ItemPrintout; | import dan200.computercraft.shared.media.items.ItemPrintout; | ||||||
| @@ -106,10 +105,9 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer | |||||||
|         transform.scale( scale, scale, scale ); |         transform.scale( scale, scale, scale ); | ||||||
|         transform.translate( (max - width) / 2.0, (max - height) / 2.0, 0.0 ); |         transform.translate( (max - width) / 2.0, (max - height) / 2.0, 0.0 ); | ||||||
| 
 | 
 | ||||||
|         Matrix4f matrix = transform.last().pose(); |         drawBorder( transform, render, 0, 0, -0.01f, 0, pages, book, light ); | ||||||
|         drawBorder( matrix, render, 0, 0, -0.01f, 0, pages, book, light ); |  | ||||||
|         drawText( |         drawText( | ||||||
|             matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, light, |             transform, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, light, | ||||||
|             ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) |             ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ | |||||||
|  */ |  */ | ||||||
| package dan200.computercraft.client.render; | package dan200.computercraft.client.render; | ||||||
| 
 | 
 | ||||||
|  | import com.mojang.blaze3d.vertex.PoseStack; | ||||||
| import com.mojang.blaze3d.vertex.VertexConsumer; | import com.mojang.blaze3d.vertex.VertexConsumer; | ||||||
| import com.mojang.math.Matrix4f; | import com.mojang.math.Matrix4f; | ||||||
| import dan200.computercraft.client.render.text.FixedWidthFontRenderer; | import dan200.computercraft.client.render.text.FixedWidthFontRenderer; | ||||||
| @@ -54,7 +55,7 @@ public final class PrintoutRenderer | |||||||
| 
 | 
 | ||||||
|     private PrintoutRenderer() {} |     private PrintoutRenderer() {} | ||||||
| 
 | 
 | ||||||
|     public static void drawText( Matrix4f transform, MultiBufferSource bufferSource, int x, int y, int start, int light, TextBuffer[] text, TextBuffer[] colours ) |     public static void drawText( PoseStack transform, MultiBufferSource bufferSource, int x, int y, int start, int light, TextBuffer[] text, TextBuffer[] colours ) | ||||||
|     { |     { | ||||||
|         var buffer = bufferSource.getBuffer( RenderTypes.PRINTOUT_TEXT ); |         var buffer = bufferSource.getBuffer( RenderTypes.PRINTOUT_TEXT ); | ||||||
|         var emitter = FixedWidthFontRenderer.toVertexConsumer( transform, buffer ); |         var emitter = FixedWidthFontRenderer.toVertexConsumer( transform, buffer ); | ||||||
| @@ -67,7 +68,7 @@ public final class PrintoutRenderer | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static void drawText( Matrix4f transform, MultiBufferSource bufferSource, int x, int y, int start, int light, String[] text, String[] colours ) |     public static void drawText( PoseStack transform, MultiBufferSource bufferSource, int x, int y, int start, int light, String[] text, String[] colours ) | ||||||
|     { |     { | ||||||
|         var buffer = bufferSource.getBuffer( RenderTypes.PRINTOUT_TEXT ); |         var buffer = bufferSource.getBuffer( RenderTypes.PRINTOUT_TEXT ); | ||||||
|         var emitter = FixedWidthFontRenderer.toVertexConsumer( transform, buffer ); |         var emitter = FixedWidthFontRenderer.toVertexConsumer( transform, buffer ); | ||||||
| @@ -81,8 +82,9 @@ public final class PrintoutRenderer | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static void drawBorder( Matrix4f transform, MultiBufferSource bufferSource, float x, float y, float z, int page, int pages, boolean isBook, int light ) |     public static void drawBorder( PoseStack transform, MultiBufferSource bufferSource, float x, float y, float z, int page, int pages, boolean isBook, int light ) | ||||||
|     { |     { | ||||||
|  |         var matrix = transform.last().pose(); | ||||||
|         int leftPages = page; |         int leftPages = page; | ||||||
|         int rightPages = pages - page - 1; |         int rightPages = pages - page - 1; | ||||||
| 
 | 
 | ||||||
| @@ -96,11 +98,11 @@ public final class PrintoutRenderer | |||||||
|             float right = x + X_SIZE + offset - 4; |             float right = x + X_SIZE + offset - 4; | ||||||
| 
 | 
 | ||||||
|             // Left and right border |             // Left and right border | ||||||
|             drawTexture( transform, buffer, left - 4, y - 8, z - 0.02f, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2, light ); |             drawTexture( matrix, 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 ); |             drawTexture( matrix, 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). |             // Draw centre panel (just stretched texture, sorry). | ||||||
|             drawTexture( transform, buffer, |             drawTexture( matrix, buffer, | ||||||
|                 x - offset, y, z - 0.02f, X_SIZE + offset * 2, Y_SIZE, |                 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 |                 light | ||||||
| @@ -110,20 +112,20 @@ public final class PrintoutRenderer | |||||||
|             while( borderX < right ) |             while( borderX < right ) | ||||||
|             { |             { | ||||||
|                 double thisWidth = Math.min( right - borderX, X_SIZE ); |                 double thisWidth = Math.min( right - borderX, X_SIZE ); | ||||||
|                 drawTexture( transform, buffer, borderX, y - 8, z - 0.02f, 0, COVER_Y, (float) thisWidth, COVER_SIZE, light ); |                 drawTexture( matrix, 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 ); |                 drawTexture( matrix, buffer, borderX, y + Y_SIZE - 4, z - 0.02f, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE, light ); | ||||||
|                 borderX += thisWidth; |                 borderX += thisWidth; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Current page background: Z-offset is interleaved between the "zeroth" left/right page and the first |         // Current page background: Z-offset is interleaved between the "zeroth" left/right page and the first | ||||||
|         // left/right page, so that the "bold" border can be drawn over the edge where appropriate. |         // left/right page, so that the "bold" border can be drawn over the edge where appropriate. | ||||||
|         drawTexture( transform, buffer, x, y, z - 1e-3f * 0.5f, X_FOLD_SIZE * 2, 0, X_SIZE, Y_SIZE, light ); |         drawTexture( matrix, buffer, x, y, z - 1e-3f * 0.5f, X_FOLD_SIZE * 2, 0, X_SIZE, Y_SIZE, light ); | ||||||
| 
 | 
 | ||||||
|         // Left pages |         // Left pages | ||||||
|         for( int n = 0; n <= leftPages; n++ ) |         for( int n = 0; n <= leftPages; n++ ) | ||||||
|         { |         { | ||||||
|             drawTexture( transform, buffer, |             drawTexture( matrix, buffer, | ||||||
|                 x - offsetAt( n ), y, z - 1e-3f * n, |                 x - offsetAt( n ), y, z - 1e-3f * n, | ||||||
|                 // Use the left "bold" fold for the outermost page |                 // Use the left "bold" fold for the outermost page | ||||||
|                 n == leftPages ? 0 : X_FOLD_SIZE, 0, |                 n == leftPages ? 0 : X_FOLD_SIZE, 0, | ||||||
| @@ -134,7 +136,7 @@ public final class PrintoutRenderer | |||||||
|         // Right pages |         // Right pages | ||||||
|         for( int n = 0; n <= rightPages; n++ ) |         for( int n = 0; n <= rightPages; n++ ) | ||||||
|         { |         { | ||||||
|             drawTexture( transform, buffer, |             drawTexture( matrix, buffer, | ||||||
|                 x + (X_SIZE - X_FOLD_SIZE) + offsetAt( n ), y, z - 1e-3f * n, |                 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. |                 // 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 * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0, | ||||||
|   | |||||||
| @@ -30,24 +30,9 @@ public class RenderTypes | |||||||
|     private static MonitorTextureBufferShader monitorTboShader; |     private static MonitorTextureBufferShader monitorTboShader; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Renders a fullbright terminal without writing to the depth layer. This is used in combination with |      * Renders a fullbright terminal. | ||||||
|      * {@link #TERMINAL_BLOCKER} to ensure we can render a terminal without z-fighting. |  | ||||||
|      */ |      */ | ||||||
|     public static final RenderType TERMINAL_WITHOUT_DEPTH = Types.TERMINAL_WITHOUT_DEPTH; |     public static final RenderType TERMINAL = RenderType.text( FixedWidthFontRenderer.FONT ); | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 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 <em>vanilla's</em> {@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; |  | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Renders a monitor with the TBO shader. |      * Renders a monitor with the TBO shader. | ||||||
| @@ -57,7 +42,7 @@ public class RenderTypes | |||||||
|     public static final RenderType MONITOR_TBO = Types.MONITOR_TBO; |     public static final RenderType MONITOR_TBO = Types.MONITOR_TBO; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * A variant of {@link #TERMINAL_WITH_DEPTH} which uses the lightmap rather than rendering fullbright. |      * A variant of {@link #TERMINAL} which uses the lightmap rather than rendering fullbright. | ||||||
|      */ |      */ | ||||||
|     public static final RenderType PRINTOUT_TEXT = RenderType.text( FixedWidthFontRenderer.FONT ); |     public static final RenderType PRINTOUT_TEXT = RenderType.text( FixedWidthFontRenderer.FONT ); | ||||||
| 
 | 
 | ||||||
| @@ -77,7 +62,7 @@ public class RenderTypes | |||||||
|     @Nonnull |     @Nonnull | ||||||
|     static ShaderInstance getTerminalShader() |     static ShaderInstance getTerminalShader() | ||||||
|     { |     { | ||||||
|         return GameRenderer.getPositionColorTexShader(); |         return GameRenderer.getRendertypeTextShader(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @SubscribeEvent |     @SubscribeEvent | ||||||
| @@ -99,8 +84,6 @@ public class RenderTypes | |||||||
|             FixedWidthFontRenderer.FONT, |             FixedWidthFontRenderer.FONT, | ||||||
|             false, false // blur, minimap |             false, false // blur, minimap | ||||||
|         ); |         ); | ||||||
|         private static final VertexFormat TERM_FORMAT = DefaultVertexFormat.POSITION_COLOR_TEX; |  | ||||||
|         private static final ShaderStateShard TERM_SHADER = new ShaderStateShard( RenderTypes::getTerminalShader ); |  | ||||||
| 
 | 
 | ||||||
|         static final RenderType MONITOR_TBO = RenderType.create( |         static final RenderType MONITOR_TBO = RenderType.create( | ||||||
|             "monitor_tbo", DefaultVertexFormat.POSITION_TEX, VertexFormat.Mode.TRIANGLE_STRIP, 128, |             "monitor_tbo", DefaultVertexFormat.POSITION_TEX, VertexFormat.Mode.TRIANGLE_STRIP, 128, | ||||||
| @@ -111,36 +94,6 @@ public class RenderTypes | |||||||
|                 .createCompositeState( false ) |                 .createCompositeState( false ) | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         static final RenderType TERMINAL_WITHOUT_DEPTH = RenderType.create( |  | ||||||
|             "terminal_without_depth", TERM_FORMAT, VertexFormat.Mode.QUADS, 1024, |  | ||||||
|             false, false, // useDelegate, needsSorting |  | ||||||
|             RenderType.CompositeState.builder() |  | ||||||
|                 .setTextureState( TERM_FONT_TEXTURE ) |  | ||||||
|                 .setShaderState( TERM_SHADER ) |  | ||||||
|                 .setLightmapState( LIGHTMAP ) |  | ||||||
|                 .setWriteMaskState( COLOR_WRITE ) |  | ||||||
|                 .createCompositeState( false ) |  | ||||||
|         ); |  | ||||||
| 
 |  | ||||||
|         static final RenderType TERMINAL_BLOCKER = RenderType.create( |  | ||||||
|             "terminal_blocker", DefaultVertexFormat.POSITION, VertexFormat.Mode.QUADS, 256, |  | ||||||
|             false, false, // useDelegate, needsSorting |  | ||||||
|             RenderType.CompositeState.builder() |  | ||||||
|                 .setShaderState( POSITION_SHADER ) |  | ||||||
|                 .setWriteMaskState( DEPTH_WRITE ) |  | ||||||
|                 .createCompositeState( false ) |  | ||||||
|         ); |  | ||||||
| 
 |  | ||||||
|         static final RenderType TERMINAL_WITH_DEPTH = RenderType.create( |  | ||||||
|             "terminal_with_depth", TERM_FORMAT, VertexFormat.Mode.QUADS, 1024, |  | ||||||
|             false, false, // useDelegate, needsSorting |  | ||||||
|             RenderType.CompositeState.builder() |  | ||||||
|                 .setTextureState( TERM_FONT_TEXTURE ) |  | ||||||
|                 .setShaderState( TERM_SHADER ) |  | ||||||
|                 .setLightmapState( LIGHTMAP ) |  | ||||||
|                 .createCompositeState( false ) |  | ||||||
|         ); |  | ||||||
| 
 |  | ||||||
|         private Types( String name, Runnable setup, Runnable destroy ) |         private Types( String name, Runnable setup, Runnable destroy ) | ||||||
|         { |         { | ||||||
|             super( name, setup, destroy ); |             super( name, setup, destroy ); | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ import com.mojang.blaze3d.vertex.BufferBuilder; | |||||||
| import com.mojang.blaze3d.vertex.PoseStack; | import com.mojang.blaze3d.vertex.PoseStack; | ||||||
| import com.mojang.blaze3d.vertex.Tesselator; | import com.mojang.blaze3d.vertex.Tesselator; | ||||||
| import com.mojang.blaze3d.vertex.VertexConsumer; | import com.mojang.blaze3d.vertex.VertexConsumer; | ||||||
|  | import com.mojang.math.Matrix3f; | ||||||
| import com.mojang.math.Matrix4f; | import com.mojang.math.Matrix4f; | ||||||
| import com.mojang.math.Vector3f; | import com.mojang.math.Vector3f; | ||||||
| import dan200.computercraft.ComputerCraft; | import dan200.computercraft.ComputerCraft; | ||||||
| @@ -19,11 +20,14 @@ import dan200.computercraft.client.FrameInfo; | |||||||
| import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer; | import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer; | ||||||
| import dan200.computercraft.client.render.text.FixedWidthFontRenderer; | import dan200.computercraft.client.render.text.FixedWidthFontRenderer; | ||||||
| import dan200.computercraft.client.util.DirectBuffers; | import dan200.computercraft.client.util.DirectBuffers; | ||||||
|  | import dan200.computercraft.client.util.DirectVertexBuffer; | ||||||
| import dan200.computercraft.core.terminal.Terminal; | import dan200.computercraft.core.terminal.Terminal; | ||||||
|  | import dan200.computercraft.shared.integration.ShaderMod; | ||||||
| import dan200.computercraft.shared.peripheral.monitor.ClientMonitor; | import dan200.computercraft.shared.peripheral.monitor.ClientMonitor; | ||||||
| import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; | import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; | ||||||
| import dan200.computercraft.shared.peripheral.monitor.TileMonitor; | import dan200.computercraft.shared.peripheral.monitor.TileMonitor; | ||||||
| import dan200.computercraft.shared.util.DirectionUtil; | import dan200.computercraft.shared.util.DirectionUtil; | ||||||
|  | import net.minecraft.Util; | ||||||
| import net.minecraft.client.renderer.MultiBufferSource; | import net.minecraft.client.renderer.MultiBufferSource; | ||||||
| import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; | import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; | ||||||
| import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; | import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; | ||||||
| @@ -35,6 +39,7 @@ import org.lwjgl.opengl.GL31; | |||||||
| 
 | 
 | ||||||
| import javax.annotation.Nonnull; | import javax.annotation.Nonnull; | ||||||
| import java.nio.ByteBuffer; | import java.nio.ByteBuffer; | ||||||
|  | import java.util.function.Consumer; | ||||||
| 
 | 
 | ||||||
| import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_HEIGHT; | 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.text.FixedWidthFontRenderer.FONT_WIDTH; | ||||||
| @@ -46,6 +51,9 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito | |||||||
|      * the monitor frame and contents. |      * the monitor frame and contents. | ||||||
|      */ |      */ | ||||||
|     private static final float MARGIN = (float) (TileMonitor.RENDER_MARGIN * 1.1); |     private static final float MARGIN = (float) (TileMonitor.RENDER_MARGIN * 1.1); | ||||||
|  | 
 | ||||||
|  |     private static final Matrix3f IDENTITY_NORMAL = Util.make( new Matrix3f(), Matrix3f::setIdentity ); | ||||||
|  | 
 | ||||||
|     private static ByteBuffer backingBuffer; |     private static ByteBuffer backingBuffer; | ||||||
| 
 | 
 | ||||||
|     public TileEntityMonitorRenderer( BlockEntityRendererProvider.Context context ) |     public TileEntityMonitorRenderer( BlockEntityRendererProvider.Context context ) | ||||||
| @@ -102,7 +110,7 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito | |||||||
| 
 | 
 | ||||||
|         // Draw the contents |         // Draw the contents | ||||||
|         Terminal terminal = originTerminal.getTerminal(); |         Terminal terminal = originTerminal.getTerminal(); | ||||||
|         if( terminal != null ) |         if( terminal != null && !ShaderMod.INSTANCE.isRenderingShadowPass() ) | ||||||
|         { |         { | ||||||
|             // Draw a terminal |             // Draw a terminal | ||||||
|             int width = terminal.getWidth(), height = terminal.getHeight(); |             int width = terminal.getWidth(), height = terminal.getHeight(); | ||||||
| @@ -121,7 +129,7 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito | |||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             FixedWidthFontRenderer.drawEmptyTerminal( |             FixedWidthFontRenderer.drawEmptyTerminal( | ||||||
|                 FixedWidthFontRenderer.toVertexConsumer( transform.last().pose(), bufferSource.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ) ), |                 FixedWidthFontRenderer.toVertexConsumer( transform, bufferSource.getBuffer( RenderTypes.TERMINAL ) ), | ||||||
|                 -MARGIN, MARGIN, |                 -MARGIN, MARGIN, | ||||||
|                 (float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2) |                 (float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2) | ||||||
|             ); |             ); | ||||||
| @@ -177,50 +185,70 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito | |||||||
| 
 | 
 | ||||||
|             case VBO: |             case VBO: | ||||||
|             { |             { | ||||||
|                 var vbo = monitor.buffer; |                 var backgroundBuffer = monitor.backgroundBuffer; | ||||||
|  |                 var foregroundBuffer = monitor.foregroundBuffer; | ||||||
|                 if( redraw ) |                 if( redraw ) | ||||||
|                 { |                 { | ||||||
|                     int vertexSize = RenderTypes.TERMINAL_WITHOUT_DEPTH.format().getVertexSize(); |                     int size = DirectFixedWidthFontRenderer.getVertexCount( terminal ); | ||||||
|                     ByteBuffer buffer = getBuffer( DirectFixedWidthFontRenderer.getVertexCount( terminal ) * vertexSize ); |  | ||||||
| 
 | 
 | ||||||
|                     // Draw the main terminal and store how many vertices it has. |                     // In an ideal world we could upload these both into one buffer. However, we can't render VBOs with | ||||||
|                     DirectFixedWidthFontRenderer.drawTerminalWithoutCursor( |                     // and starting and ending offset, and so need to use two buffers instead. | ||||||
|                         buffer, 0, 0, terminal, !monitor.isColour(), yMargin, yMargin, xMargin, xMargin |  | ||||||
|                     ); |  | ||||||
|                     int termIndexes = buffer.position() / vertexSize; |  | ||||||
| 
 | 
 | ||||||
|  |                     renderToBuffer( backgroundBuffer, size, sink -> | ||||||
|  |                         DirectFixedWidthFontRenderer.drawTerminalBackground( sink, 0, 0, terminal, !monitor.isColour(), yMargin, yMargin, xMargin, xMargin ) ); | ||||||
|  | 
 | ||||||
|  |                     renderToBuffer( foregroundBuffer, size, sink -> { | ||||||
|  |                         DirectFixedWidthFontRenderer.drawTerminalForeground( sink, 0, 0, terminal, !monitor.isColour() ); | ||||||
|                         // If the cursor is visible, we append it to the end of our buffer. When rendering, we can either |                         // If the cursor is visible, we append it to the end of our buffer. When rendering, we can either | ||||||
|                         // render n or n+1 quads and so toggle the cursor on and off. |                         // render n or n+1 quads and so toggle the cursor on and off. | ||||||
|                     DirectFixedWidthFontRenderer.drawCursor( buffer, 0, 0, terminal, !monitor.isColour() ); |                         DirectFixedWidthFontRenderer.drawCursor( sink, 0, 0, terminal, !monitor.isColour() ); | ||||||
| 
 |                     } ); | ||||||
|                     buffer.flip(); |  | ||||||
| 
 |  | ||||||
|                     vbo.upload( termIndexes, RenderTypes.TERMINAL_WITHOUT_DEPTH.mode(), RenderTypes.TERMINAL_WITHOUT_DEPTH.format(), buffer ); |  | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 RenderTypes.TERMINAL_WITHOUT_DEPTH.setupRenderState(); |                 // Our VBO doesn't transform its vertices with the provided pose stack, which means that the inverse view | ||||||
|                 vbo.drawWithShader( |                 // rotation matrix gives entirely wrong numbers for fog distances. We just set it to the identity which | ||||||
|  |                 // gives a good enough approximation. | ||||||
|  |                 Matrix3f oldInverseRotation = RenderSystem.getInverseViewRotationMatrix(); | ||||||
|  |                 RenderSystem.setInverseViewRotationMatrix( IDENTITY_NORMAL ); | ||||||
|  | 
 | ||||||
|  |                 RenderTypes.TERMINAL.setupRenderState(); | ||||||
|  | 
 | ||||||
|  |                 // Render background geometry | ||||||
|  |                 backgroundBuffer.drawWithShader( matrix, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader() ); | ||||||
|  | 
 | ||||||
|  |                 // Render foreground geometry with glPolygonOffset enabled. | ||||||
|  |                 GL11.glPolygonOffset( -1.0f, -10.0f ); | ||||||
|  |                 GL11.glEnable( GL11.GL_POLYGON_OFFSET_FILL ); | ||||||
|  |                 foregroundBuffer.drawWithShader( | ||||||
|                     matrix, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader(), |                     matrix, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader(), | ||||||
|                     // As mentioned in the above comment, render the extra cursor quad if it is visible this frame. Each |                     // As mentioned in the above comment, render the extra cursor quad if it is visible this frame. Each | ||||||
|                     // // quad has an index count of 6. |                     // // quad has an index count of 6. | ||||||
|                     FixedWidthFontRenderer.isCursorVisible( terminal ) && FrameInfo.getGlobalCursorBlink() ? vbo.getIndexCount() + 6 : vbo.getIndexCount() |                     FixedWidthFontRenderer.isCursorVisible( terminal ) && FrameInfo.getGlobalCursorBlink() | ||||||
|  |                         ? foregroundBuffer.getIndexCount() + 6 : foregroundBuffer.getIndexCount() | ||||||
|                 ); |                 ); | ||||||
|                 RenderTypes.TERMINAL_WITHOUT_DEPTH.clearRenderState(); |  | ||||||
| 
 | 
 | ||||||
|                 // TERMINAL_WITHOUT_DEPTH doesn't write to the depth blocker, so write a blocker over the monitor. |                 // Clear state | ||||||
|                 BufferBuilder buffer = Tesselator.getInstance().getBuilder(); |                 GL11.glPolygonOffset( 0.0f, -0.0f ); | ||||||
|                 buffer.begin( RenderTypes.TERMINAL_BLOCKER.mode(), RenderTypes.TERMINAL_BLOCKER.format() ); |                 GL11.glDisable( GL11.GL_POLYGON_OFFSET_FILL ); | ||||||
|                 FixedWidthFontRenderer.drawBlocker( |                 RenderTypes.TERMINAL.clearRenderState(); | ||||||
|                     FixedWidthFontRenderer.toVertexConsumer( matrix, buffer ), | 
 | ||||||
|                     -xMargin, -yMargin, pixelWidth + xMargin * 2, pixelHeight + yMargin * 2 |                 RenderSystem.setInverseViewRotationMatrix( oldInverseRotation ); | ||||||
|                 ); |  | ||||||
|                 RenderTypes.TERMINAL_BLOCKER.end( buffer, 0, 0, 0 ); |  | ||||||
| 
 | 
 | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private static void renderToBuffer( DirectVertexBuffer vbo, int size, Consumer<DirectFixedWidthFontRenderer.QuadEmitter> draw ) | ||||||
|  |     { | ||||||
|  |         var sink = ShaderMod.INSTANCE.getQuadEmitter( size, TileEntityMonitorRenderer::getBuffer ); | ||||||
|  |         var buffer = sink.buffer(); | ||||||
|  | 
 | ||||||
|  |         draw.accept( sink ); | ||||||
|  |         buffer.flip(); | ||||||
|  |         vbo.upload( buffer.limit() / sink.format().getVertexSize(), RenderTypes.TERMINAL.mode(), sink.format(), buffer ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private static void tboVertex( VertexConsumer builder, Matrix4f matrix, float x, float y ) |     private static void tboVertex( VertexConsumer builder, Matrix4f matrix, float x, float y ) | ||||||
|     { |     { | ||||||
|         // We encode position in the UV, as that's not transformed by the matrix. |         // We encode position in the UV, as that's not transformed by the matrix. | ||||||
|   | |||||||
| @@ -8,6 +8,8 @@ package dan200.computercraft.client.render.text; | |||||||
| import com.mojang.blaze3d.platform.MemoryTracker; | import com.mojang.blaze3d.platform.MemoryTracker; | ||||||
| import com.mojang.blaze3d.vertex.DefaultVertexFormat; | import com.mojang.blaze3d.vertex.DefaultVertexFormat; | ||||||
| import com.mojang.blaze3d.vertex.VertexConsumer; | import com.mojang.blaze3d.vertex.VertexConsumer; | ||||||
|  | import com.mojang.blaze3d.vertex.VertexFormat; | ||||||
|  | import dan200.computercraft.client.render.RenderTypes; | ||||||
| import dan200.computercraft.core.terminal.Terminal; | import dan200.computercraft.core.terminal.Terminal; | ||||||
| import dan200.computercraft.core.terminal.TextBuffer; | import dan200.computercraft.core.terminal.TextBuffer; | ||||||
| import dan200.computercraft.shared.util.Colour; | import dan200.computercraft.shared.util.Colour; | ||||||
| @@ -18,17 +20,16 @@ import javax.annotation.Nonnull; | |||||||
| import java.nio.ByteBuffer; | import java.nio.ByteBuffer; | ||||||
| 
 | 
 | ||||||
| import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.*; | import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.*; | ||||||
| import static org.lwjgl.system.MemoryUtil.memPutByte; | import static org.lwjgl.system.MemoryUtil.*; | ||||||
| import static org.lwjgl.system.MemoryUtil.memPutFloat; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * An optimised copy of {@link FixedWidthFontRenderer} emitter emits directly to a {@link ByteBuffer} rather than |  * An optimised copy of {@link FixedWidthFontRenderer} emitter emits directly to a {@link QuadEmitter} rather than | ||||||
|  * emitting to {@link VertexConsumer}. This allows us to emit vertices very quickly, when using the VBO renderer. |  * emitting to {@link VertexConsumer}. This allows us to emit vertices very quickly, when using the VBO renderer. | ||||||
|  * |  * | ||||||
|  * There are some limitations here: |  * There are some limitations here: | ||||||
|  * <ul> |  * <ul> | ||||||
|  *   <li>No transformation matrix (not needed for VBOs).</li> |  *   <li>No transformation matrix (not needed for VBOs).</li> | ||||||
|  *   <li>Only works with {@link DefaultVertexFormat#POSITION_COLOR_TEX}.</li> |  *   <li>Only works with {@link DefaultVertexFormat#POSITION_COLOR_TEX_LIGHTMAP}.</li> | ||||||
|  *   <li>The buffer <strong>MUST</strong> be allocated with {@link MemoryTracker}, and not through any other means.</li> |  *   <li>The buffer <strong>MUST</strong> be allocated with {@link MemoryTracker}, and not through any other means.</li> | ||||||
|  * </ul> |  * </ul> | ||||||
|  * |  * | ||||||
| @@ -44,7 +45,7 @@ public final class DirectFixedWidthFontRenderer | |||||||
|     { |     { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static void drawChar( ByteBuffer buffer, float x, float y, int index, byte[] colour ) |     private static void drawChar( QuadEmitter emitter, float x, float y, int index, byte[] colour ) | ||||||
|     { |     { | ||||||
|         // Short circuit to avoid the common case - the texture should be blank here after all. |         // Short circuit to avoid the common case - the texture should be blank here after all. | ||||||
|         if( index == '\0' || index == ' ' ) return; |         if( index == '\0' || index == ' ' ) return; | ||||||
| @@ -56,30 +57,30 @@ public final class DirectFixedWidthFontRenderer | |||||||
|         int yStart = 1 + row * (FONT_HEIGHT + 2); |         int yStart = 1 + row * (FONT_HEIGHT + 2); | ||||||
| 
 | 
 | ||||||
|         quad( |         quad( | ||||||
|             buffer, x, y, x + FONT_WIDTH, y + FONT_HEIGHT, colour, |             emitter, x, y, x + FONT_WIDTH, y + FONT_HEIGHT, 0, colour, | ||||||
|             xStart / WIDTH, yStart / WIDTH, (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH |             xStart / WIDTH, yStart / WIDTH, (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static void drawQuad( ByteBuffer emitter, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex ) |     private static void drawQuad( QuadEmitter emitter, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex ) | ||||||
|     { |     { | ||||||
|         byte[] colour = palette.getByteColour( getColour( colourIndex, Colour.BLACK ), greyscale ); |         byte[] colour = palette.getByteColour( getColour( colourIndex, Colour.BLACK ), greyscale ); | ||||||
|         quad( emitter, x, y, x + width, y + height, colour, BACKGROUND_START, BACKGROUND_START, BACKGROUND_END, BACKGROUND_END ); |         quad( emitter, x, y, x + width, y + height, 0f, colour, BACKGROUND_START, BACKGROUND_START, BACKGROUND_END, BACKGROUND_END ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static void drawBackground( |     private static void drawBackground( | ||||||
|         @Nonnull ByteBuffer buffer, float x, float y, @Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, |         @Nonnull QuadEmitter emitter, float x, float y, @Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, | ||||||
|         float leftMarginSize, float rightMarginSize, float height |         float leftMarginSize, float rightMarginSize, float height | ||||||
|     ) |     ) | ||||||
|     { |     { | ||||||
|         if( leftMarginSize > 0 ) |         if( leftMarginSize > 0 ) | ||||||
|         { |         { | ||||||
|             drawQuad( buffer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) ); |             drawQuad( emitter, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) ); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if( rightMarginSize > 0 ) |         if( rightMarginSize > 0 ) | ||||||
|         { |         { | ||||||
|             drawQuad( buffer, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, greyscale, backgroundColour.charAt( backgroundColour.length() - 1 ) ); |             drawQuad( emitter, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, greyscale, backgroundColour.charAt( backgroundColour.length() - 1 ) ); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Batch together runs of identical background cells. |         // Batch together runs of identical background cells. | ||||||
| @@ -92,7 +93,7 @@ public final class DirectFixedWidthFontRenderer | |||||||
| 
 | 
 | ||||||
|             if( blockColour != '\0' ) |             if( blockColour != '\0' ) | ||||||
|             { |             { | ||||||
|                 drawQuad( buffer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour ); |                 drawQuad( emitter, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour ); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             blockColour = colourIndex; |             blockColour = colourIndex; | ||||||
| @@ -101,11 +102,11 @@ public final class DirectFixedWidthFontRenderer | |||||||
| 
 | 
 | ||||||
|         if( blockColour != '\0' ) |         if( blockColour != '\0' ) | ||||||
|         { |         { | ||||||
|             drawQuad( buffer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, greyscale, blockColour ); |             drawQuad( emitter, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, greyscale, blockColour ); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static void drawString( @Nonnull ByteBuffer buffer, float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nonnull Palette palette, boolean greyscale ) |     public static void drawString( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nonnull Palette palette, boolean greyscale ) | ||||||
|     { |     { | ||||||
|         for( int i = 0; i < text.length(); i++ ) |         for( int i = 0; i < text.length(); i++ ) | ||||||
|         { |         { | ||||||
| @@ -113,12 +114,29 @@ public final class DirectFixedWidthFontRenderer | |||||||
| 
 | 
 | ||||||
|             int index = text.charAt( i ); |             int index = text.charAt( i ); | ||||||
|             if( index > 255 ) index = '?'; |             if( index > 255 ) index = '?'; | ||||||
|             drawChar( buffer, x + i * FONT_WIDTH, y, index, colour ); |             drawChar( emitter, x + i * FONT_WIDTH, y, index, colour ); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void drawTerminalForeground( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal, boolean greyscale ) | ||||||
|  |     { | ||||||
|  |         Palette palette = terminal.getPalette(); | ||||||
|  |         int height = terminal.getHeight(); | ||||||
|  | 
 | ||||||
|  |         // The main text | ||||||
|  |         for( int i = 0; i < height; i++ ) | ||||||
|  |         { | ||||||
|  |             float rowY = y + FONT_HEIGHT * i; | ||||||
|  |             drawString( | ||||||
|  |                 emitter, x, rowY, terminal.getLine( i ), terminal.getTextColourLine( i ), | ||||||
|  |                 palette, greyscale | ||||||
|  |             ); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static void drawTerminalWithoutCursor( |     public static void drawTerminalBackground( | ||||||
|         @Nonnull ByteBuffer buffer, float x, float y, @Nonnull Terminal terminal, boolean greyscale, |         @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal, boolean greyscale, | ||||||
|         float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize |         float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize | ||||||
|     ) |     ) | ||||||
|     { |     { | ||||||
| @@ -127,12 +145,12 @@ public final class DirectFixedWidthFontRenderer | |||||||
| 
 | 
 | ||||||
|         // Top and bottom margins |         // Top and bottom margins | ||||||
|         drawBackground( |         drawBackground( | ||||||
|             buffer, x, y - topMarginSize, terminal.getBackgroundColourLine( 0 ), palette, greyscale, |             emitter, x, y - topMarginSize, terminal.getBackgroundColourLine( 0 ), palette, greyscale, | ||||||
|             leftMarginSize, rightMarginSize, topMarginSize |             leftMarginSize, rightMarginSize, topMarginSize | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         drawBackground( |         drawBackground( | ||||||
|             buffer, x, y + height * FONT_HEIGHT, terminal.getBackgroundColourLine( height - 1 ), palette, greyscale, |             emitter, x, y + height * FONT_HEIGHT, terminal.getBackgroundColourLine( height - 1 ), palette, greyscale, | ||||||
|             leftMarginSize, rightMarginSize, bottomMarginSize |             leftMarginSize, rightMarginSize, bottomMarginSize | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
| @@ -141,43 +159,68 @@ public final class DirectFixedWidthFontRenderer | |||||||
|         { |         { | ||||||
|             float rowY = y + FONT_HEIGHT * i; |             float rowY = y + FONT_HEIGHT * i; | ||||||
|             drawBackground( |             drawBackground( | ||||||
|                 buffer, x, rowY, terminal.getBackgroundColourLine( i ), palette, greyscale, |                 emitter, x, rowY, terminal.getBackgroundColourLine( i ), palette, greyscale, | ||||||
|                 leftMarginSize, rightMarginSize, FONT_HEIGHT |                 leftMarginSize, rightMarginSize, FONT_HEIGHT | ||||||
|             ); |             ); | ||||||
|             drawString( |  | ||||||
|                 buffer, x, rowY, terminal.getLine( i ), terminal.getTextColourLine( i ), |  | ||||||
|                 palette, greyscale |  | ||||||
|             ); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static void drawCursor( @Nonnull ByteBuffer buffer, float x, float y, @Nonnull Terminal terminal, boolean greyscale ) |     public static void drawCursor( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal, boolean greyscale ) | ||||||
|     { |     { | ||||||
|         if( isCursorVisible( terminal ) ) |         if( isCursorVisible( terminal ) ) | ||||||
|         { |         { | ||||||
|             byte[] colour = terminal.getPalette().getByteColour( 15 - terminal.getTextColour(), greyscale ); |             byte[] colour = terminal.getPalette().getByteColour( 15 - terminal.getTextColour(), greyscale ); | ||||||
|             drawChar( buffer, x + terminal.getCursorX() * FONT_WIDTH, y + terminal.getCursorY() * FONT_HEIGHT, '_', colour ); |             drawChar( emitter, x + terminal.getCursorX() * FONT_WIDTH, y + terminal.getCursorY() * FONT_HEIGHT, '_', colour ); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static int getVertexCount( Terminal terminal ) |     public static int getVertexCount( Terminal terminal ) | ||||||
|     { |     { | ||||||
|         return (1 + (terminal.getHeight() + 2) * terminal.getWidth() * 2) * 4; |         return (terminal.getHeight() + 2) * (terminal.getWidth() + 2) * 2; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static void quad( ByteBuffer buffer, float x1, float y1, float x2, float y2, byte[] rgba, float u1, float v1, float u2, float v2 ) |     private static void quad( QuadEmitter buffer, float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2 ) | ||||||
|  |     { | ||||||
|  |         buffer.quad( x1, y1, x2, y2, z, rgba, u1, v1, u2, v2 ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public interface QuadEmitter | ||||||
|  |     { | ||||||
|  |         VertexFormat format(); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer buffer(); | ||||||
|  | 
 | ||||||
|  |         void quad( float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2 ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public record ByteBufferEmitter(ByteBuffer buffer) implements QuadEmitter | ||||||
|  |     { | ||||||
|  |         @Override | ||||||
|  |         public VertexFormat format() | ||||||
|  |         { | ||||||
|  |             return RenderTypes.TERMINAL.format(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void quad( float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2 ) | ||||||
|  |         { | ||||||
|  |             DirectFixedWidthFontRenderer.quad( buffer, x1, y1, x2, y2, z, rgba, u1, v1, u2, v2 ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     static void quad( ByteBuffer buffer, float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2 ) | ||||||
|     { |     { | ||||||
|         // Emit a single quad to our buffer. This uses Unsafe (well, LWJGL's MemoryUtil) to directly blit bytes to the |         // Emit a single quad to our buffer. This uses Unsafe (well, LWJGL's MemoryUtil) to directly blit bytes to the | ||||||
|         // underlying buffer. This allows us to have a single bounds check up-front, rather than one for every write. |         // underlying buffer. This allows us to have a single bounds check up-front, rather than one for every write. | ||||||
|         // This provides significant performance gains, at the cost of well, using Unsafe. |         // This provides significant performance gains, at the cost of well, using Unsafe. | ||||||
|         // Each vertex is 24 bytes, giving 96 bytes in total. Vertices are of the form (xyz:FFF)(rgba:BBBB)(uv:FF), |         // Each vertex is 28 bytes, giving 112 bytes in total. Vertices are of the form (xyz:FFF)(rgba:BBBB)(uv1:FF)(uv2:SS), | ||||||
|         // which matches the POSITION_COLOR_TEX vertex format. |         // which matches the POSITION_COLOR_TEX_LIGHTMAP vertex format. | ||||||
| 
 | 
 | ||||||
|         int position = buffer.position(); |         int position = buffer.position(); | ||||||
|         long addr = MemoryUtil.memAddress( buffer ); |         long addr = MemoryUtil.memAddress( buffer ); | ||||||
| 
 | 
 | ||||||
|         // We're doing terrible unsafe hacks below, so let's be really sure that what we're doing is reasonable. |         // We're doing terrible unsafe hacks below, so let's be really sure that what we're doing is reasonable. | ||||||
|         if( position < 0 || 96 > buffer.limit() - position ) throw new IndexOutOfBoundsException(); |         if( position < 0 || 112 > buffer.limit() - position ) throw new IndexOutOfBoundsException(); | ||||||
|         // Require the pointer to be aligned to a 32-bit boundary. |         // Require the pointer to be aligned to a 32-bit boundary. | ||||||
|         if( (addr & 3) != 0 ) throw new IllegalStateException( "Memory is not aligned" ); |         if( (addr & 3) != 0 ) throw new IllegalStateException( "Memory is not aligned" ); | ||||||
|         // Also assert the length of the array. This appears to help elide bounds checks on the array in some circumstances. |         // Also assert the length of the array. This appears to help elide bounds checks on the array in some circumstances. | ||||||
| @@ -185,46 +228,54 @@ public final class DirectFixedWidthFontRenderer | |||||||
| 
 | 
 | ||||||
|         memPutFloat( addr + 0, x1 ); |         memPutFloat( addr + 0, x1 ); | ||||||
|         memPutFloat( addr + 4, y1 ); |         memPutFloat( addr + 4, y1 ); | ||||||
|         memPutFloat( addr + 8, 0 ); |         memPutFloat( addr + 8, z ); | ||||||
|         memPutByte( addr + 12, rgba[0] ); |         memPutByte( addr + 12, rgba[0] ); | ||||||
|         memPutByte( addr + 13, rgba[1] ); |         memPutByte( addr + 13, rgba[1] ); | ||||||
|         memPutByte( addr + 14, rgba[2] ); |         memPutByte( addr + 14, rgba[2] ); | ||||||
|         memPutByte( addr + 15, (byte) 255 ); |         memPutByte( addr + 15, (byte) 255 ); | ||||||
|         memPutFloat( addr + 16, u1 ); |         memPutFloat( addr + 16, u1 ); | ||||||
|         memPutFloat( addr + 20, v1 ); |         memPutFloat( addr + 20, v1 ); | ||||||
|  |         memPutShort( addr + 24, (short) 0xF0 ); | ||||||
|  |         memPutShort( addr + 26, (short) 0xF0 ); | ||||||
| 
 | 
 | ||||||
|         memPutFloat( addr + 24, x1 ); |         memPutFloat( addr + 28, x1 ); | ||||||
|         memPutFloat( addr + 28, y2 ); |         memPutFloat( addr + 32, y2 ); | ||||||
|         memPutFloat( addr + 32, 0 ); |         memPutFloat( addr + 36, z ); | ||||||
|         memPutByte( addr + 36, rgba[0] ); |         memPutByte( addr + 40, rgba[0] ); | ||||||
|         memPutByte( addr + 37, rgba[1] ); |         memPutByte( addr + 41, rgba[1] ); | ||||||
|         memPutByte( addr + 38, rgba[2] ); |         memPutByte( addr + 42, rgba[2] ); | ||||||
|         memPutByte( addr + 39, (byte) 255 ); |         memPutByte( addr + 43, (byte) 255 ); | ||||||
|         memPutFloat( addr + 40, u1 ); |         memPutFloat( addr + 44, u1 ); | ||||||
|         memPutFloat( addr + 44, v2 ); |         memPutFloat( addr + 48, v2 ); | ||||||
|  |         memPutShort( addr + 52, (short) 0xF0 ); | ||||||
|  |         memPutShort( addr + 54, (short) 0xF0 ); | ||||||
| 
 | 
 | ||||||
|         memPutFloat( addr + 48, x2 ); |         memPutFloat( addr + 56, x2 ); | ||||||
|         memPutFloat( addr + 52, y2 ); |         memPutFloat( addr + 60, y2 ); | ||||||
|         memPutFloat( addr + 56, 0 ); |         memPutFloat( addr + 64, z ); | ||||||
|         memPutByte( addr + 60, rgba[0] ); |         memPutByte( addr + 68, rgba[0] ); | ||||||
|         memPutByte( addr + 61, rgba[1] ); |         memPutByte( addr + 69, rgba[1] ); | ||||||
|         memPutByte( addr + 62, rgba[2] ); |         memPutByte( addr + 70, rgba[2] ); | ||||||
|         memPutByte( addr + 63, (byte) 255 ); |         memPutByte( addr + 71, (byte) 255 ); | ||||||
|         memPutFloat( addr + 64, u2 ); |         memPutFloat( addr + 72, u2 ); | ||||||
|         memPutFloat( addr + 68, v2 ); |         memPutFloat( addr + 76, v2 ); | ||||||
|  |         memPutShort( addr + 80, (short) 0xF0 ); | ||||||
|  |         memPutShort( addr + 82, (short) 0xF0 ); | ||||||
| 
 | 
 | ||||||
|         memPutFloat( addr + 72, x2 ); |         memPutFloat( addr + 84, x2 ); | ||||||
|         memPutFloat( addr + 76, y1 ); |         memPutFloat( addr + 88, y1 ); | ||||||
|         memPutFloat( addr + 80, 0 ); |         memPutFloat( addr + 92, z ); | ||||||
|         memPutByte( addr + 84, rgba[0] ); |         memPutByte( addr + 96, rgba[0] ); | ||||||
|         memPutByte( addr + 85, rgba[1] ); |         memPutByte( addr + 97, rgba[1] ); | ||||||
|         memPutByte( addr + 86, rgba[2] ); |         memPutByte( addr + 98, rgba[2] ); | ||||||
|         memPutByte( addr + 87, (byte) 255 ); |         memPutByte( addr + 99, (byte) 255 ); | ||||||
|         memPutFloat( addr + 88, u2 ); |         memPutFloat( addr + 100, u2 ); | ||||||
|         memPutFloat( addr + 92, v1 ); |         memPutFloat( addr + 104, v1 ); | ||||||
|  |         memPutShort( addr + 108, (short) 0xF0 ); | ||||||
|  |         memPutShort( addr + 110, (short) 0xF0 ); | ||||||
| 
 | 
 | ||||||
|         // Finally increment the position. |         // Finally increment the position. | ||||||
|         buffer.position( position + 96 ); |         buffer.position( position + 112 ); | ||||||
| 
 | 
 | ||||||
|         // Well done for getting to the end of this method. I recommend you take a break and go look at cute puppies. |         // Well done for getting to the end of this method. I recommend you take a break and go look at cute puppies. | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -5,10 +5,11 @@ | |||||||
|  */ |  */ | ||||||
| package dan200.computercraft.client.render.text; | package dan200.computercraft.client.render.text; | ||||||
| 
 | 
 | ||||||
|  | import com.mojang.blaze3d.vertex.PoseStack; | ||||||
| import com.mojang.blaze3d.vertex.VertexConsumer; | import com.mojang.blaze3d.vertex.VertexConsumer; | ||||||
| import com.mojang.math.Matrix4f; | import com.mojang.math.Matrix4f; | ||||||
|  | import com.mojang.math.Vector3f; | ||||||
| import dan200.computercraft.client.FrameInfo; | import dan200.computercraft.client.FrameInfo; | ||||||
| import dan200.computercraft.client.render.RenderTypes; |  | ||||||
| import dan200.computercraft.core.terminal.Terminal; | import dan200.computercraft.core.terminal.Terminal; | ||||||
| import dan200.computercraft.core.terminal.TextBuffer; | import dan200.computercraft.core.terminal.TextBuffer; | ||||||
| import dan200.computercraft.shared.util.Colour; | import dan200.computercraft.shared.util.Colour; | ||||||
| @@ -26,13 +27,8 @@ import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMA | |||||||
|  * <ul> |  * <ul> | ||||||
|  * <li>{@link #drawString}: Drawing basic text without a terminal (such as for printouts). Unlike the other methods, |  * <li>{@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.</li> |  * this accepts a lightmap coordinate as, unlike terminals, printed pages render fullbright.</li> | ||||||
|  * <li>{@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. |  | ||||||
|  * </li> |  | ||||||
|  * <li>{@link #drawTerminal}: Draw a terminal with a cursor. This is used by the various computer GUIs to render the |  * <li>{@link #drawTerminal}: Draw a terminal with a cursor. This is used by the various computer GUIs to render the | ||||||
|  * whole term.</li> |  * whole term.</li> | ||||||
|  * <li>{@link #drawBlocker}: When rendering a terminal using {@link RenderTypes#TERMINAL_WITHOUT_DEPTH} you need to |  | ||||||
|  * render an additional "depth blocker" on top of the monitor.</li> |  | ||||||
|  * </ul> |  * </ul> | ||||||
|  * |  * | ||||||
|  * <strong>IMPORTANT: </strong> When making changes to this class, please check if you need to make the same changes to |  * <strong>IMPORTANT: </strong> When making changes to this class, please check if you need to make the same changes to | ||||||
| @@ -50,6 +46,7 @@ public final class FixedWidthFontRenderer | |||||||
|     static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH; |     static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH; | ||||||
| 
 | 
 | ||||||
|     private static final byte[] BLACK = new byte[] { byteColour( Colour.BLACK.getR() ), byteColour( Colour.BLACK.getR() ), byteColour( Colour.BLACK.getR() ), (byte) 255 }; |     private static final byte[] BLACK = new byte[] { byteColour( Colour.BLACK.getR() ), byteColour( Colour.BLACK.getR() ), byteColour( Colour.BLACK.getR() ), (byte) 255 }; | ||||||
|  |     private static final float Z_OFFSET = 1e-3f; | ||||||
| 
 | 
 | ||||||
|     private FixedWidthFontRenderer() |     private FixedWidthFontRenderer() | ||||||
|     { |     { | ||||||
| @@ -149,9 +146,24 @@ public final class FixedWidthFontRenderer | |||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static void drawTerminalWithoutCursor( |     public static void drawTerminalForeground( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal, boolean greyscale ) | ||||||
|         @Nonnull QuadEmitter emitter, float x, float y, |     { | ||||||
|         @Nonnull Terminal terminal, boolean greyscale, |         Palette palette = terminal.getPalette(); | ||||||
|  |         int height = terminal.getHeight(); | ||||||
|  | 
 | ||||||
|  |         // The main text | ||||||
|  |         for( int i = 0; i < height; i++ ) | ||||||
|  |         { | ||||||
|  |             float rowY = y + FONT_HEIGHT * i; | ||||||
|  |             drawString( | ||||||
|  |                 emitter, x, rowY, terminal.getLine( i ), terminal.getTextColourLine( i ), | ||||||
|  |                 palette, greyscale, FULL_BRIGHT_LIGHTMAP | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void drawTerminalBackground( | ||||||
|  |         @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal, boolean greyscale, | ||||||
|         float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize |         float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize | ||||||
|     ) |     ) | ||||||
|     { |     { | ||||||
| @@ -172,15 +184,11 @@ public final class FixedWidthFontRenderer | |||||||
|         // The main text |         // The main text | ||||||
|         for( int i = 0; i < height; i++ ) |         for( int i = 0; i < height; i++ ) | ||||||
|         { |         { | ||||||
|             float rowY = y + FixedWidthFontRenderer.FONT_HEIGHT * i; |             float rowY = y + FONT_HEIGHT * i; | ||||||
|             drawBackground( |             drawBackground( | ||||||
|                 emitter, x, rowY, terminal.getBackgroundColourLine( i ), palette, greyscale, |                 emitter, x, rowY, terminal.getBackgroundColourLine( i ), palette, greyscale, | ||||||
|                 leftMarginSize, rightMarginSize, FONT_HEIGHT, FULL_BRIGHT_LIGHTMAP |                 leftMarginSize, rightMarginSize, FONT_HEIGHT, FULL_BRIGHT_LIGHTMAP | ||||||
|             ); |             ); | ||||||
|             drawString( |  | ||||||
|                 emitter, x, rowY, terminal.getLine( i ), terminal.getTextColourLine( i ), |  | ||||||
|                 palette, greyscale, FULL_BRIGHT_LIGHTMAP |  | ||||||
|             ); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @@ -208,8 +216,21 @@ public final class FixedWidthFontRenderer | |||||||
|         float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize |         float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize | ||||||
|     ) |     ) | ||||||
|     { |     { | ||||||
|         drawTerminalWithoutCursor( emitter, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); |         drawTerminalBackground( | ||||||
|  |             emitter, x, y, terminal, greyscale, | ||||||
|  |             topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         // Render the foreground with a slight offset. By calling .translate() on the matrix itself, we're translating | ||||||
|  |         // in screen space, rather than in model/view space. | ||||||
|  |         // It's definitely not perfect, but better than z fighting! | ||||||
|  |         var transformBackup = emitter.poseMatrix().copy(); | ||||||
|  |         emitter.poseMatrix().translate( new Vector3f( 0, 0, Z_OFFSET ) ); | ||||||
|  | 
 | ||||||
|  |         drawTerminalForeground( emitter, x, y, terminal, greyscale ); | ||||||
|         drawCursor( emitter, x, y, terminal, greyscale ); |         drawCursor( emitter, x, y, terminal, greyscale ); | ||||||
|  | 
 | ||||||
|  |         emitter.poseMatrix().load( transformBackup ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static void drawEmptyTerminal( @Nonnull QuadEmitter emitter, float x, float y, float width, float height ) |     public static void drawEmptyTerminal( @Nonnull QuadEmitter emitter, float x, float y, float width, float height ) | ||||||
| @@ -217,27 +238,24 @@ public final class FixedWidthFontRenderer | |||||||
|         drawQuad( emitter, x, y, 0, width, height, BLACK, FULL_BRIGHT_LIGHTMAP ); |         drawQuad( emitter, x, y, 0, width, height, BLACK, FULL_BRIGHT_LIGHTMAP ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static void drawBlocker( @Nonnull QuadEmitter emitter, float x, float y, float width, float height ) |     public record QuadEmitter(Matrix4f poseMatrix, VertexConsumer consumer) | ||||||
|     { |     { | ||||||
|         drawQuad( emitter, x, y, 0, width, height, BLACK, FULL_BRIGHT_LIGHTMAP ); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public record QuadEmitter(Matrix4f matrix4f, VertexConsumer consumer) {} |     public static QuadEmitter toVertexConsumer( PoseStack transform, VertexConsumer consumer ) | ||||||
| 
 |  | ||||||
|     public static QuadEmitter toVertexConsumer( Matrix4f matrix, VertexConsumer consumer ) |  | ||||||
|     { |     { | ||||||
|         return new QuadEmitter( matrix, consumer ); |         return new QuadEmitter( transform.last().pose(), consumer ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static void quad( QuadEmitter c, float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2, int light ) |     private static void quad( QuadEmitter c, float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2, int light ) | ||||||
|     { |     { | ||||||
|         var matrix = c.matrix4f(); |         var poseMatrix = c.poseMatrix(); | ||||||
|         var consumer = c.consumer(); |         var consumer = c.consumer(); | ||||||
|         byte r = rgba[0], g = rgba[1], b = rgba[2], a = rgba[3]; |         byte r = rgba[0], g = rgba[1], b = rgba[2], a = rgba[3]; | ||||||
| 
 | 
 | ||||||
|         consumer.vertex( matrix, x1, y1, z ).color( r, g, b, a ).uv( u1, v1 ).uv2( light ).endVertex(); |         consumer.vertex( poseMatrix, x1, y1, z ).color( r, g, b, a ).uv( u1, v1 ).uv2( light ).endVertex(); | ||||||
|         consumer.vertex( matrix, x1, y2, z ).color( r, g, b, a ).uv( u1, v2 ).uv2( light ).endVertex(); |         consumer.vertex( poseMatrix, x1, y2, z ).color( r, g, b, a ).uv( u1, v2 ).uv2( light ).endVertex(); | ||||||
|         consumer.vertex( matrix, x2, y2, z ).color( r, g, b, a ).uv( u2, v2 ).uv2( light ).endVertex(); |         consumer.vertex( poseMatrix, x2, y2, z ).color( r, g, b, a ).uv( u2, v2 ).uv2( light ).endVertex(); | ||||||
|         consumer.vertex( matrix, x2, y1, z ).color( r, g, b, a ).uv( u2, v1 ).uv2( light ).endVertex(); |         consumer.vertex( poseMatrix, x2, y1, z ).color( r, g, b, a ).uv( u2, v1 ).uv2( light ).endVertex(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,96 @@ | |||||||
|  | /* | ||||||
|  |  * 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.shared.integration; | ||||||
|  | 
 | ||||||
|  | import com.mojang.blaze3d.vertex.VertexFormat; | ||||||
|  | import dan200.computercraft.client.render.RenderTypes; | ||||||
|  | import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer; | ||||||
|  | import net.irisshaders.iris.api.v0.IrisApi; | ||||||
|  | import net.irisshaders.iris.api.v0.IrisTextVertexSink; | ||||||
|  | import net.minecraftforge.fml.ModList; | ||||||
|  | 
 | ||||||
|  | import java.nio.ByteBuffer; | ||||||
|  | import java.util.function.IntFunction; | ||||||
|  | 
 | ||||||
|  | public class ShaderMod | ||||||
|  | { | ||||||
|  |     public static final ShaderMod INSTANCE | ||||||
|  |         = ModList.get().isLoaded( "oculus" ) ? new IrisImpl() | ||||||
|  |         : new ShaderMod(); | ||||||
|  | 
 | ||||||
|  |     public boolean isShaderMod() | ||||||
|  |     { | ||||||
|  |         return Optifine.isLoaded(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public boolean isRenderingShadowPass() | ||||||
|  |     { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter( int vertexCount, IntFunction<ByteBuffer> makeBuffer ) | ||||||
|  |     { | ||||||
|  |         return new DirectFixedWidthFontRenderer.ByteBufferEmitter( | ||||||
|  |             makeBuffer.apply( RenderTypes.TERMINAL.format().getVertexSize() * vertexCount * 4 ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static final class IrisImpl extends ShaderMod | ||||||
|  |     { | ||||||
|  |         @Override | ||||||
|  |         public boolean isRenderingShadowPass() | ||||||
|  |         { | ||||||
|  |             return IrisApi.getInstance().isRenderingShadowPass(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean isShaderMod() | ||||||
|  |         { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter( int vertexCount, IntFunction<ByteBuffer> makeBuffer ) | ||||||
|  |         { | ||||||
|  |             return IrisApi.getInstance().getMinorApiRevision() >= 1 | ||||||
|  |                 ? new IrisQuadEmitter( vertexCount, makeBuffer ) | ||||||
|  |                 : super.getQuadEmitter( vertexCount, makeBuffer ); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static final class IrisQuadEmitter implements DirectFixedWidthFontRenderer.QuadEmitter | ||||||
|  |         { | ||||||
|  |             private final IrisTextVertexSink sink; | ||||||
|  | 
 | ||||||
|  |             private IrisQuadEmitter( int vertexCount, IntFunction<ByteBuffer> makeBuffer ) | ||||||
|  |             { | ||||||
|  |                 sink = IrisApi.getInstance().createTextVertexSink( vertexCount, makeBuffer ); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             @Override | ||||||
|  |             public VertexFormat format() | ||||||
|  |             { | ||||||
|  |                 return sink.getUnderlyingVertexFormat(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             @Override | ||||||
|  |             public ByteBuffer buffer() | ||||||
|  |             { | ||||||
|  |                 return sink.getUnderlyingByteBuffer(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             @Override | ||||||
|  |             public void quad( float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2 ) | ||||||
|  |             { | ||||||
|  |                 sink.quad( x1, y1, x2, y2, z, pack( rgba[0], rgba[1], rgba[2], rgba[3] ), u1, v1, u2, v2, RenderTypes.FULL_BRIGHT_LIGHTMAP ); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             private static int pack( int r, int g, int b, int a ) | ||||||
|  |             { | ||||||
|  |                 return (a & 255) << 24 | (b & 255) << 16 | (g & 255) << 8 | r & 255; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -33,7 +33,8 @@ public final class ClientMonitor extends ClientTerminal | |||||||
|     public int tboBuffer; |     public int tboBuffer; | ||||||
|     public int tboTexture; |     public int tboTexture; | ||||||
|     public int tboUniform; |     public int tboUniform; | ||||||
|     public DirectVertexBuffer buffer; |     public DirectVertexBuffer backgroundBuffer; | ||||||
|  |     public DirectVertexBuffer foregroundBuffer; | ||||||
| 
 | 
 | ||||||
|     public ClientMonitor( boolean colour, TileMonitor origin ) |     public ClientMonitor( boolean colour, TileMonitor origin ) | ||||||
|     { |     { | ||||||
| @@ -79,10 +80,11 @@ public final class ClientMonitor extends ClientTerminal | |||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             case VBO: |             case VBO: | ||||||
|                 if( buffer != null ) return false; |                 if( backgroundBuffer != null ) return false; | ||||||
| 
 | 
 | ||||||
|                 deleteBuffers(); |                 deleteBuffers(); | ||||||
|                 buffer = new DirectVertexBuffer(); |                 backgroundBuffer = new DirectVertexBuffer(); | ||||||
|  |                 foregroundBuffer = new DirectVertexBuffer(); | ||||||
|                 addMonitor(); |                 addMonitor(); | ||||||
|                 return true; |                 return true; | ||||||
| 
 | 
 | ||||||
| @@ -120,17 +122,23 @@ public final class ClientMonitor extends ClientTerminal | |||||||
|             tboUniform = 0; |             tboUniform = 0; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if( buffer != null ) |         if( backgroundBuffer != null ) | ||||||
|         { |         { | ||||||
|             buffer.close(); |             backgroundBuffer.close(); | ||||||
|             buffer = null; |             backgroundBuffer = null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if( foregroundBuffer != null ) | ||||||
|  |         { | ||||||
|  |             foregroundBuffer.close(); | ||||||
|  |             foregroundBuffer = null; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @OnlyIn( Dist.CLIENT ) |     @OnlyIn( Dist.CLIENT ) | ||||||
|     public void destroy() |     public void destroy() | ||||||
|     { |     { | ||||||
|         if( tboBuffer != 0 || buffer != null ) |         if( tboBuffer != 0 || backgroundBuffer != null ) | ||||||
|         { |         { | ||||||
|             synchronized( allMonitors ) |             synchronized( allMonitors ) | ||||||
|             { |             { | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ package dan200.computercraft.shared.peripheral.monitor; | |||||||
| 
 | 
 | ||||||
| import dan200.computercraft.ComputerCraft; | import dan200.computercraft.ComputerCraft; | ||||||
| import dan200.computercraft.client.render.TileEntityMonitorRenderer; | import dan200.computercraft.client.render.TileEntityMonitorRenderer; | ||||||
| import dan200.computercraft.shared.integration.Optifine; | import dan200.computercraft.shared.integration.ShaderMod; | ||||||
| import org.lwjgl.opengl.GL; | import org.lwjgl.opengl.GL; | ||||||
| 
 | 
 | ||||||
| import javax.annotation.Nonnull; | import javax.annotation.Nonnull; | ||||||
| @@ -60,7 +60,7 @@ public enum MonitorRenderer | |||||||
|             return VBO; |             return VBO; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if( Optifine.isLoaded() ) |         if( ShaderMod.INSTANCE.isShaderMod() ) | ||||||
|         { |         { | ||||||
|             ComputerCraft.log.warn( "Optifine is loaded, assuming shaders are being used. Falling back to VBO monitor renderer." ); |             ComputerCraft.log.warn( "Optifine is loaded, assuming shaders are being used. Falling back to VBO monitor renderer." ); | ||||||
|             return VBO; |             return VBO; | ||||||
|   | |||||||
| @@ -16,10 +16,10 @@ class Disk_Drive_Test { | |||||||
|      * |      * | ||||||
|      * @see [#688](https://github.com/cc-tweaked/CC-Tweaked/issues/688) |      * @see [#688](https://github.com/cc-tweaked/CC-Tweaked/issues/688) | ||||||
|      */ |      */ | ||||||
|     @GameTest |     @GameTest(timeoutTicks = Modem_Test.TIMEOUT) | ||||||
|     fun Audio_disk(helper: GameTestHelper) = helper.sequence { thenComputerOk() } |     fun Audio_disk(helper: GameTestHelper) = helper.sequence { thenComputerOk() } | ||||||
| 
 | 
 | ||||||
|     @GameTest |     @GameTest(timeoutTicks = Modem_Test.TIMEOUT) | ||||||
|     fun Ejects_disk(helper: GameTestHelper) = helper.sequence { |     fun Ejects_disk(helper: GameTestHelper) = helper.sequence { | ||||||
|         val stackAt = BlockPos(2, 2, 2) |         val stackAt = BlockPos(2, 2, 2) | ||||||
|         this |         this | ||||||
|   | |||||||
| @@ -77,7 +77,7 @@ class Turtle_Test { | |||||||
|      * |      * | ||||||
|      * Currently not required as turtles can no longer right-click cauldrons. |      * Currently not required as turtles can no longer right-click cauldrons. | ||||||
|      */ |      */ | ||||||
|     @GameTest(required = false) |     @GameTest(timeoutTicks = COMPUTER_TIMEOUT, required = false) | ||||||
|     fun Cleaned_with_cauldrons(helper: GameTestHelper) = helper.sequence { thenComputerOk() } |     fun Cleaned_with_cauldrons(helper: GameTestHelper) = helper.sequence { thenComputerOk() } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates