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-common-api: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 '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.vertex.PoseStack; | ||||
| import com.mojang.blaze3d.vertex.Tesselator; | ||||
| import com.mojang.math.Matrix4f; | ||||
| import dan200.computercraft.core.terminal.TextBuffer; | ||||
| import dan200.computercraft.shared.common.ContainerHeldItem; | ||||
| import dan200.computercraft.shared.media.items.ItemPrintout; | ||||
| @@ -99,9 +98,8 @@ public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem> | ||||
|         RenderSystem.enableDepthTest(); | ||||
| 
 | ||||
|         MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() ); | ||||
|         Matrix4f matrix = transform.last().pose(); | ||||
|         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 ); | ||||
|         drawBorder( transform, 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 ); | ||||
|         renderer.endBatch(); | ||||
|     } | ||||
| 
 | ||||
|   | ||||
| @@ -7,7 +7,6 @@ package dan200.computercraft.client.gui.widgets; | ||||
| 
 | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import com.mojang.blaze3d.vertex.Tesselator; | ||||
| import com.mojang.math.Matrix4f; | ||||
| import dan200.computercraft.client.render.RenderTypes; | ||||
| import dan200.computercraft.client.render.text.FixedWidthFontRenderer; | ||||
| 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 ) | ||||
|     { | ||||
|         if( !visible ) return; | ||||
|         Matrix4f matrix = transform.last().pose(); | ||||
|         Terminal terminal = computer.getTerminal(); | ||||
| 
 | ||||
|         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 ) | ||||
|         { | ||||
|   | ||||
| @@ -96,23 +96,19 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer | ||||
|         // Render the light | ||||
|         int lightColour = ItemPocketComputer.getLightState( stack ); | ||||
|         if( lightColour == -1 ) lightColour = Colour.BLACK.getHex(); | ||||
|         renderLight( matrix, bufferSource, lightColour, width, height ); | ||||
|         renderLight( transform, bufferSource, lightColour, width, height ); | ||||
| 
 | ||||
|         if( computer != null && terminal != null ) | ||||
|         { | ||||
|             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 | ||||
|             ); | ||||
|             FixedWidthFontRenderer.drawBlocker( | ||||
|                 FixedWidthFontRenderer.toVertexConsumer( matrix, bufferSource.getBuffer( RenderTypes.TERMINAL_BLOCKER ) ), | ||||
|                 0, 0, width, height | ||||
|             ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             FixedWidthFontRenderer.drawEmptyTerminal( | ||||
|                 FixedWidthFontRenderer.toVertexConsumer( matrix, bufferSource.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ) ), | ||||
|                 FixedWidthFontRenderer.toVertexConsumer( transform, bufferSource.getBuffer( RenderTypes.TERMINAL ) ), | ||||
|                 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 ); | ||||
|     } | ||||
| 
 | ||||
|     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 g = (byte) ((colour >>> 8) & 0xFF); | ||||
|         byte b = (byte) (colour & 0xFF); | ||||
|         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.toVertexConsumer( transform, buffer ), | ||||
|             width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0.001f, LIGHT_HEIGHT * 2, LIGHT_HEIGHT, | ||||
|   | ||||
| @@ -6,7 +6,6 @@ | ||||
| package dan200.computercraft.client.render; | ||||
| 
 | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import com.mojang.math.Matrix4f; | ||||
| import com.mojang.math.Vector3f; | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import dan200.computercraft.shared.media.items.ItemPrintout; | ||||
| @@ -106,10 +105,9 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer | ||||
|         transform.scale( scale, scale, scale ); | ||||
|         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, light ); | ||||
|         drawBorder( transform, render, 0, 0, -0.01f, 0, pages, book, light ); | ||||
|         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 ) | ||||
|         ); | ||||
|     } | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
|  */ | ||||
| package dan200.computercraft.client.render; | ||||
| 
 | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import com.mojang.blaze3d.vertex.VertexConsumer; | ||||
| import com.mojang.math.Matrix4f; | ||||
| import dan200.computercraft.client.render.text.FixedWidthFontRenderer; | ||||
| @@ -54,7 +55,7 @@ public final class 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 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 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 rightPages = pages - page - 1; | ||||
| 
 | ||||
| @@ -96,11 +98,11 @@ 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, 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, left - 4, y - 8, z - 0.02f, COVER_X, 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). | ||||
|             drawTexture( transform, buffer, | ||||
|             drawTexture( matrix, 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, | ||||
|                 light | ||||
| @@ -110,20 +112,20 @@ public final class PrintoutRenderer | ||||
|             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, 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 - 8, z - 0.02f, 0, COVER_Y, (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; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // 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. | ||||
|         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 | ||||
|         for( int n = 0; n <= leftPages; n++ ) | ||||
|         { | ||||
|             drawTexture( transform, buffer, | ||||
|             drawTexture( matrix, 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, | ||||
| @@ -134,7 +136,7 @@ public final class PrintoutRenderer | ||||
|         // Right pages | ||||
|         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, | ||||
|                 // 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, | ||||
|   | ||||
| @@ -30,24 +30,9 @@ public class RenderTypes | ||||
|     private static MonitorTextureBufferShader monitorTboShader; | ||||
| 
 | ||||
|     /** | ||||
|      * 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. | ||||
|      * Renders a fullbright terminal. | ||||
|      */ | ||||
|     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 <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; | ||||
|     public static final RenderType TERMINAL = RenderType.text( FixedWidthFontRenderer.FONT ); | ||||
| 
 | ||||
|     /** | ||||
|      * Renders a monitor with the TBO shader. | ||||
| @@ -57,7 +42,7 @@ public class RenderTypes | ||||
|     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 ); | ||||
| 
 | ||||
| @@ -77,7 +62,7 @@ public class RenderTypes | ||||
|     @Nonnull | ||||
|     static ShaderInstance getTerminalShader() | ||||
|     { | ||||
|         return GameRenderer.getPositionColorTexShader(); | ||||
|         return GameRenderer.getRendertypeTextShader(); | ||||
|     } | ||||
| 
 | ||||
|     @SubscribeEvent | ||||
| @@ -99,8 +84,6 @@ public class RenderTypes | ||||
|             FixedWidthFontRenderer.FONT, | ||||
|             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( | ||||
|             "monitor_tbo", DefaultVertexFormat.POSITION_TEX, VertexFormat.Mode.TRIANGLE_STRIP, 128, | ||||
| @@ -111,36 +94,6 @@ public class RenderTypes | ||||
|                 .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 ) | ||||
|         { | ||||
|             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.Tesselator; | ||||
| import com.mojang.blaze3d.vertex.VertexConsumer; | ||||
| import com.mojang.math.Matrix3f; | ||||
| import com.mojang.math.Matrix4f; | ||||
| import com.mojang.math.Vector3f; | ||||
| 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.FixedWidthFontRenderer; | ||||
| import dan200.computercraft.client.util.DirectBuffers; | ||||
| import dan200.computercraft.client.util.DirectVertexBuffer; | ||||
| 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.MonitorRenderer; | ||||
| import dan200.computercraft.shared.peripheral.monitor.TileMonitor; | ||||
| import dan200.computercraft.shared.util.DirectionUtil; | ||||
| import net.minecraft.Util; | ||||
| import net.minecraft.client.renderer.MultiBufferSource; | ||||
| import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; | ||||
| import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; | ||||
| @@ -35,6 +39,7 @@ import org.lwjgl.opengl.GL31; | ||||
| 
 | ||||
| import javax.annotation.Nonnull; | ||||
| 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_WIDTH; | ||||
| @@ -46,6 +51,9 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito | ||||
|      * the monitor frame and contents. | ||||
|      */ | ||||
|     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; | ||||
| 
 | ||||
|     public TileEntityMonitorRenderer( BlockEntityRendererProvider.Context context ) | ||||
| @@ -102,7 +110,7 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito | ||||
| 
 | ||||
|         // Draw the contents | ||||
|         Terminal terminal = originTerminal.getTerminal(); | ||||
|         if( terminal != null ) | ||||
|         if( terminal != null && !ShaderMod.INSTANCE.isRenderingShadowPass() ) | ||||
|         { | ||||
|             // Draw a terminal | ||||
|             int width = terminal.getWidth(), height = terminal.getHeight(); | ||||
| @@ -121,7 +129,7 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito | ||||
|         else | ||||
|         { | ||||
|             FixedWidthFontRenderer.drawEmptyTerminal( | ||||
|                 FixedWidthFontRenderer.toVertexConsumer( transform.last().pose(), bufferSource.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ) ), | ||||
|                 FixedWidthFontRenderer.toVertexConsumer( transform, bufferSource.getBuffer( RenderTypes.TERMINAL ) ), | ||||
|                 -MARGIN, MARGIN, | ||||
|                 (float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2) | ||||
|             ); | ||||
| @@ -177,50 +185,70 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito | ||||
| 
 | ||||
|             case VBO: | ||||
|             { | ||||
|                 var vbo = monitor.buffer; | ||||
|                 var backgroundBuffer = monitor.backgroundBuffer; | ||||
|                 var foregroundBuffer = monitor.foregroundBuffer; | ||||
|                 if( redraw ) | ||||
|                 { | ||||
|                     int vertexSize = RenderTypes.TERMINAL_WITHOUT_DEPTH.format().getVertexSize(); | ||||
|                     ByteBuffer buffer = getBuffer( DirectFixedWidthFontRenderer.getVertexCount( terminal ) * vertexSize ); | ||||
|                     int size = DirectFixedWidthFontRenderer.getVertexCount( terminal ); | ||||
| 
 | ||||
|                     // Draw the main terminal and store how many vertices it has. | ||||
|                     DirectFixedWidthFontRenderer.drawTerminalWithoutCursor( | ||||
|                         buffer, 0, 0, terminal, !monitor.isColour(), yMargin, yMargin, xMargin, xMargin | ||||
|                     ); | ||||
|                     int termIndexes = buffer.position() / vertexSize; | ||||
|                     // In an ideal world we could upload these both into one buffer. However, we can't render VBOs with | ||||
|                     // and starting and ending offset, and so need to use two buffers instead. | ||||
| 
 | ||||
|                     // 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. | ||||
|                     DirectFixedWidthFontRenderer.drawCursor( buffer, 0, 0, terminal, !monitor.isColour() ); | ||||
|                     renderToBuffer( backgroundBuffer, size, sink -> | ||||
|                         DirectFixedWidthFontRenderer.drawTerminalBackground( sink, 0, 0, terminal, !monitor.isColour(), yMargin, yMargin, xMargin, xMargin ) ); | ||||
| 
 | ||||
|                     buffer.flip(); | ||||
| 
 | ||||
|                     vbo.upload( termIndexes, RenderTypes.TERMINAL_WITHOUT_DEPTH.mode(), RenderTypes.TERMINAL_WITHOUT_DEPTH.format(), buffer ); | ||||
|                     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 | ||||
|                         // render n or n+1 quads and so toggle the cursor on and off. | ||||
|                         DirectFixedWidthFontRenderer.drawCursor( sink, 0, 0, terminal, !monitor.isColour() ); | ||||
|                     } ); | ||||
|                 } | ||||
| 
 | ||||
|                 RenderTypes.TERMINAL_WITHOUT_DEPTH.setupRenderState(); | ||||
|                 vbo.drawWithShader( | ||||
|                 // Our VBO doesn't transform its vertices with the provided pose stack, which means that the inverse view | ||||
|                 // 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(), | ||||
|                     // 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. | ||||
|                     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. | ||||
|                 BufferBuilder buffer = Tesselator.getInstance().getBuilder(); | ||||
|                 buffer.begin( RenderTypes.TERMINAL_BLOCKER.mode(), RenderTypes.TERMINAL_BLOCKER.format() ); | ||||
|                 FixedWidthFontRenderer.drawBlocker( | ||||
|                     FixedWidthFontRenderer.toVertexConsumer( matrix, buffer ), | ||||
|                     -xMargin, -yMargin, pixelWidth + xMargin * 2, pixelHeight + yMargin * 2 | ||||
|                 ); | ||||
|                 RenderTypes.TERMINAL_BLOCKER.end( buffer, 0, 0, 0 ); | ||||
|                 // Clear state | ||||
|                 GL11.glPolygonOffset( 0.0f, -0.0f ); | ||||
|                 GL11.glDisable( GL11.GL_POLYGON_OFFSET_FILL ); | ||||
|                 RenderTypes.TERMINAL.clearRenderState(); | ||||
| 
 | ||||
|                 RenderSystem.setInverseViewRotationMatrix( oldInverseRotation ); | ||||
| 
 | ||||
|                 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 ) | ||||
|     { | ||||
|         // 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.vertex.DefaultVertexFormat; | ||||
| 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.TextBuffer; | ||||
| import dan200.computercraft.shared.util.Colour; | ||||
| @@ -18,17 +20,16 @@ import javax.annotation.Nonnull; | ||||
| import java.nio.ByteBuffer; | ||||
| 
 | ||||
| import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.*; | ||||
| import static org.lwjgl.system.MemoryUtil.memPutByte; | ||||
| import static org.lwjgl.system.MemoryUtil.memPutFloat; | ||||
| import static org.lwjgl.system.MemoryUtil.*; | ||||
| 
 | ||||
| /** | ||||
|  * 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. | ||||
|  * | ||||
|  * There are some limitations here: | ||||
|  * <ul> | ||||
|  *   <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> | ||||
|  * </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. | ||||
|         if( index == '\0' || index == ' ' ) return; | ||||
| @@ -56,30 +57,30 @@ public final class DirectFixedWidthFontRenderer | ||||
|         int yStart = 1 + row * (FONT_HEIGHT + 2); | ||||
| 
 | ||||
|         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 | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     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 ); | ||||
|         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( | ||||
|         @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 | ||||
|     ) | ||||
|     { | ||||
|         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 ) | ||||
|         { | ||||
|             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. | ||||
| @@ -92,7 +93,7 @@ public final class DirectFixedWidthFontRenderer | ||||
| 
 | ||||
|             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; | ||||
| @@ -101,11 +102,11 @@ public final class DirectFixedWidthFontRenderer | ||||
| 
 | ||||
|         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++ ) | ||||
|         { | ||||
| @@ -113,12 +114,29 @@ public final class DirectFixedWidthFontRenderer | ||||
| 
 | ||||
|             int index = text.charAt( i ); | ||||
|             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( | ||||
|         @Nonnull ByteBuffer buffer, float x, float y, @Nonnull Terminal terminal, boolean greyscale, | ||||
|     public static void drawTerminalBackground( | ||||
|         @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal, boolean greyscale, | ||||
|         float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize | ||||
|     ) | ||||
|     { | ||||
| @@ -127,12 +145,12 @@ public final class DirectFixedWidthFontRenderer | ||||
| 
 | ||||
|         // Top and bottom margins | ||||
|         drawBackground( | ||||
|             buffer, x, y - topMarginSize, terminal.getBackgroundColourLine( 0 ), palette, greyscale, | ||||
|             emitter, x, y - topMarginSize, terminal.getBackgroundColourLine( 0 ), palette, greyscale, | ||||
|             leftMarginSize, rightMarginSize, topMarginSize | ||||
|         ); | ||||
| 
 | ||||
|         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 | ||||
|         ); | ||||
| 
 | ||||
| @@ -141,43 +159,68 @@ public final class DirectFixedWidthFontRenderer | ||||
|         { | ||||
|             float rowY = y + FONT_HEIGHT * i; | ||||
|             drawBackground( | ||||
|                 buffer, x, rowY, terminal.getBackgroundColourLine( i ), palette, greyscale, | ||||
|                 emitter, x, rowY, terminal.getBackgroundColourLine( i ), palette, greyscale, | ||||
|                 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 ) ) | ||||
|         { | ||||
|             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 ) | ||||
|     { | ||||
|         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 | ||||
|         // 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. | ||||
|         // Each vertex is 24 bytes, giving 96 bytes in total. Vertices are of the form (xyz:FFF)(rgba:BBBB)(uv:FF), | ||||
|         // which matches the POSITION_COLOR_TEX vertex format. | ||||
|         // 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_LIGHTMAP vertex format. | ||||
| 
 | ||||
|         int position = buffer.position(); | ||||
|         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. | ||||
|         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. | ||||
|         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. | ||||
| @@ -185,46 +228,54 @@ public final class DirectFixedWidthFontRenderer | ||||
| 
 | ||||
|         memPutFloat( addr + 0, x1 ); | ||||
|         memPutFloat( addr + 4, y1 ); | ||||
|         memPutFloat( addr + 8, 0 ); | ||||
|         memPutFloat( addr + 8, z ); | ||||
|         memPutByte( addr + 12, rgba[0] ); | ||||
|         memPutByte( addr + 13, rgba[1] ); | ||||
|         memPutByte( addr + 14, rgba[2] ); | ||||
|         memPutByte( addr + 15, (byte) 255 ); | ||||
|         memPutFloat( addr + 16, u1 ); | ||||
|         memPutFloat( addr + 20, v1 ); | ||||
|         memPutShort( addr + 24, (short) 0xF0 ); | ||||
|         memPutShort( addr + 26, (short) 0xF0 ); | ||||
| 
 | ||||
|         memPutFloat( addr + 24, x1 ); | ||||
|         memPutFloat( addr + 28, y2 ); | ||||
|         memPutFloat( addr + 32, 0 ); | ||||
|         memPutByte( addr + 36, rgba[0] ); | ||||
|         memPutByte( addr + 37, rgba[1] ); | ||||
|         memPutByte( addr + 38, rgba[2] ); | ||||
|         memPutByte( addr + 39, (byte) 255 ); | ||||
|         memPutFloat( addr + 40, u1 ); | ||||
|         memPutFloat( addr + 44, v2 ); | ||||
|         memPutFloat( addr + 28, x1 ); | ||||
|         memPutFloat( addr + 32, y2 ); | ||||
|         memPutFloat( addr + 36, z ); | ||||
|         memPutByte( addr + 40, rgba[0] ); | ||||
|         memPutByte( addr + 41, rgba[1] ); | ||||
|         memPutByte( addr + 42, rgba[2] ); | ||||
|         memPutByte( addr + 43, (byte) 255 ); | ||||
|         memPutFloat( addr + 44, u1 ); | ||||
|         memPutFloat( addr + 48, v2 ); | ||||
|         memPutShort( addr + 52, (short) 0xF0 ); | ||||
|         memPutShort( addr + 54, (short) 0xF0 ); | ||||
| 
 | ||||
|         memPutFloat( addr + 48, x2 ); | ||||
|         memPutFloat( addr + 52, y2 ); | ||||
|         memPutFloat( addr + 56, 0 ); | ||||
|         memPutByte( addr + 60, rgba[0] ); | ||||
|         memPutByte( addr + 61, rgba[1] ); | ||||
|         memPutByte( addr + 62, rgba[2] ); | ||||
|         memPutByte( addr + 63, (byte) 255 ); | ||||
|         memPutFloat( addr + 64, u2 ); | ||||
|         memPutFloat( addr + 68, v2 ); | ||||
|         memPutFloat( addr + 56, x2 ); | ||||
|         memPutFloat( addr + 60, y2 ); | ||||
|         memPutFloat( addr + 64, z ); | ||||
|         memPutByte( addr + 68, rgba[0] ); | ||||
|         memPutByte( addr + 69, rgba[1] ); | ||||
|         memPutByte( addr + 70, rgba[2] ); | ||||
|         memPutByte( addr + 71, (byte) 255 ); | ||||
|         memPutFloat( addr + 72, u2 ); | ||||
|         memPutFloat( addr + 76, v2 ); | ||||
|         memPutShort( addr + 80, (short) 0xF0 ); | ||||
|         memPutShort( addr + 82, (short) 0xF0 ); | ||||
| 
 | ||||
|         memPutFloat( addr + 72, x2 ); | ||||
|         memPutFloat( addr + 76, y1 ); | ||||
|         memPutFloat( addr + 80, 0 ); | ||||
|         memPutByte( addr + 84, rgba[0] ); | ||||
|         memPutByte( addr + 85, rgba[1] ); | ||||
|         memPutByte( addr + 86, rgba[2] ); | ||||
|         memPutByte( addr + 87, (byte) 255 ); | ||||
|         memPutFloat( addr + 88, u2 ); | ||||
|         memPutFloat( addr + 92, v1 ); | ||||
|         memPutFloat( addr + 84, x2 ); | ||||
|         memPutFloat( addr + 88, y1 ); | ||||
|         memPutFloat( addr + 92, z ); | ||||
|         memPutByte( addr + 96, rgba[0] ); | ||||
|         memPutByte( addr + 97, rgba[1] ); | ||||
|         memPutByte( addr + 98, rgba[2] ); | ||||
|         memPutByte( addr + 99, (byte) 255 ); | ||||
|         memPutFloat( addr + 100, u2 ); | ||||
|         memPutFloat( addr + 104, v1 ); | ||||
|         memPutShort( addr + 108, (short) 0xF0 ); | ||||
|         memPutShort( addr + 110, (short) 0xF0 ); | ||||
| 
 | ||||
|         // 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. | ||||
|     } | ||||
|   | ||||
| @@ -5,10 +5,11 @@ | ||||
|  */ | ||||
| package dan200.computercraft.client.render.text; | ||||
| 
 | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import com.mojang.blaze3d.vertex.VertexConsumer; | ||||
| import com.mojang.math.Matrix4f; | ||||
| import com.mojang.math.Vector3f; | ||||
| import dan200.computercraft.client.FrameInfo; | ||||
| import dan200.computercraft.client.render.RenderTypes; | ||||
| import dan200.computercraft.core.terminal.Terminal; | ||||
| import dan200.computercraft.core.terminal.TextBuffer; | ||||
| import dan200.computercraft.shared.util.Colour; | ||||
| @@ -26,13 +27,8 @@ import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMA | ||||
|  * <ul> | ||||
|  * <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> | ||||
|  * <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 | ||||
|  * 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> | ||||
|  * | ||||
|  * <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; | ||||
| 
 | ||||
|     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() | ||||
|     { | ||||
| @@ -149,9 +146,24 @@ public final class FixedWidthFontRenderer | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public static void drawTerminalWithoutCursor( | ||||
|         @Nonnull QuadEmitter emitter, float x, float y, | ||||
|         @Nonnull Terminal terminal, boolean greyscale, | ||||
|     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, 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 | ||||
|     ) | ||||
|     { | ||||
| @@ -172,15 +184,11 @@ public final class FixedWidthFontRenderer | ||||
|         // The main text | ||||
|         for( int i = 0; i < height; i++ ) | ||||
|         { | ||||
|             float rowY = y + FixedWidthFontRenderer.FONT_HEIGHT * i; | ||||
|             float rowY = y + FONT_HEIGHT * i; | ||||
|             drawBackground( | ||||
|                 emitter, x, rowY, terminal.getBackgroundColourLine( i ), palette, greyscale, | ||||
|                 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 | ||||
|     ) | ||||
|     { | ||||
|         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 ); | ||||
| 
 | ||||
|         emitter.poseMatrix().load( transformBackup ); | ||||
|     } | ||||
| 
 | ||||
|     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 ); | ||||
|     } | ||||
| 
 | ||||
|     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( Matrix4f matrix, VertexConsumer consumer ) | ||||
|     public static QuadEmitter toVertexConsumer( PoseStack transform, 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 ) | ||||
|     { | ||||
|         var matrix = c.matrix4f(); | ||||
|         var poseMatrix = c.poseMatrix(); | ||||
|         var consumer = c.consumer(); | ||||
|         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( matrix, 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( matrix, x2, y1, z ).color( r, g, b, a ).uv( u2, v1 ).uv2( light ).endVertex(); | ||||
|         consumer.vertex( poseMatrix, x1, y1, z ).color( r, g, b, a ).uv( u1, v1 ).uv2( light ).endVertex(); | ||||
|         consumer.vertex( poseMatrix, x1, y2, z ).color( r, g, b, a ).uv( u1, v2 ).uv2( light ).endVertex(); | ||||
|         consumer.vertex( poseMatrix, x2, y2, z ).color( r, g, b, a ).uv( u2, v2 ).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 tboTexture; | ||||
|     public int tboUniform; | ||||
|     public DirectVertexBuffer buffer; | ||||
|     public DirectVertexBuffer backgroundBuffer; | ||||
|     public DirectVertexBuffer foregroundBuffer; | ||||
| 
 | ||||
|     public ClientMonitor( boolean colour, TileMonitor origin ) | ||||
|     { | ||||
| @@ -79,10 +80,11 @@ public final class ClientMonitor extends ClientTerminal | ||||
|             } | ||||
| 
 | ||||
|             case VBO: | ||||
|                 if( buffer != null ) return false; | ||||
|                 if( backgroundBuffer != null ) return false; | ||||
| 
 | ||||
|                 deleteBuffers(); | ||||
|                 buffer = new DirectVertexBuffer(); | ||||
|                 backgroundBuffer = new DirectVertexBuffer(); | ||||
|                 foregroundBuffer = new DirectVertexBuffer(); | ||||
|                 addMonitor(); | ||||
|                 return true; | ||||
| 
 | ||||
| @@ -120,17 +122,23 @@ public final class ClientMonitor extends ClientTerminal | ||||
|             tboUniform = 0; | ||||
|         } | ||||
| 
 | ||||
|         if( buffer != null ) | ||||
|         if( backgroundBuffer != null ) | ||||
|         { | ||||
|             buffer.close(); | ||||
|             buffer = null; | ||||
|             backgroundBuffer.close(); | ||||
|             backgroundBuffer = null; | ||||
|         } | ||||
| 
 | ||||
|         if( foregroundBuffer != null ) | ||||
|         { | ||||
|             foregroundBuffer.close(); | ||||
|             foregroundBuffer = null; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @OnlyIn( Dist.CLIENT ) | ||||
|     public void destroy() | ||||
|     { | ||||
|         if( tboBuffer != 0 || buffer != null ) | ||||
|         if( tboBuffer != 0 || backgroundBuffer != null ) | ||||
|         { | ||||
|             synchronized( allMonitors ) | ||||
|             { | ||||
|   | ||||
| @@ -7,7 +7,7 @@ package dan200.computercraft.shared.peripheral.monitor; | ||||
| 
 | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import dan200.computercraft.client.render.TileEntityMonitorRenderer; | ||||
| import dan200.computercraft.shared.integration.Optifine; | ||||
| import dan200.computercraft.shared.integration.ShaderMod; | ||||
| import org.lwjgl.opengl.GL; | ||||
| 
 | ||||
| import javax.annotation.Nonnull; | ||||
| @@ -60,7 +60,7 @@ public enum MonitorRenderer | ||||
|             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." ); | ||||
|             return VBO; | ||||
|   | ||||
| @@ -16,10 +16,10 @@ class Disk_Drive_Test { | ||||
|      * | ||||
|      * @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() } | ||||
| 
 | ||||
|     @GameTest | ||||
|     @GameTest(timeoutTicks = Modem_Test.TIMEOUT) | ||||
|     fun Ejects_disk(helper: GameTestHelper) = helper.sequence { | ||||
|         val stackAt = BlockPos(2, 2, 2) | ||||
|         this | ||||
|   | ||||
| @@ -77,7 +77,7 @@ class Turtle_Test { | ||||
|      * | ||||
|      * 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() } | ||||
| 
 | ||||
|     /** | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates