From d8bb05f30ebc6c4c4ed5ebec71acc644227cff06 Mon Sep 17 00:00:00 2001 From: Merith Date: Sun, 27 Mar 2022 15:13:53 -0700 Subject: [PATCH] [Iris] Merge Rendering Experiments to 1.18.2 (#78) * Quick and dirty test. - VBO monitor renderer path has been hijacked to test not using VBOs, instead we recreate the terminal geometry every frame. - Add an explicit call the BufferSource.endBatch(). This actually fixes the incompatibility with Batched Entity Rendering. Who knew it was that easy? Results: works with Iris without shaders enabled. * Use entity RenderType for rendering terminals in world. - FixedWidthFontRenderer now emits quads and fills out all the vertex elements needed for the entity vertex format, which is, well, *all* of them. - FixedWidthFontRenderer now takes a PoseStack so it can offset the char quads from the background. - TERMINAL_MODE changed to quads so remaining custom RenderTypes work with FWFR. New progress at this commit: - Iris and Canvas both render the hi-jacked VBO backend properly. Issues: - Char quads have a blacker background than empty quads due to mismatched lightmaps. - Items in hand have improper normals. - TBO renderer is untested. Need to make sure it wasn't broken. * More stuff Progress: - "VBO" code path now works fine with shaders. - Printout GUI has lightmap issue. - Pocket computer frames don't have right normals in world. - Pocket computer lights don't work. TODOs: - Investigate whether VBOs can be used again without breaking compat. If not, the code path needs to be renamed and the code for managing VBO resources should be removed. - Make sure TBO code path still works. Wouldn't be surprised if I broke something there. * Found a new rendertype for monitors, fixed normals Progress: - Monitors render fullbright in every direction. - Normals are right on pocket computers and printouts, so lighting effects like directional light and shadow maps looks correct. - BEST monitor renderer settings will detect shader mods and automatically enable shader compatible code path. Details: - The "textIntensity" rendertype is exactaly what we need for monitors. It's shader doesn't apply a directional light so monitors look fullbright consistent no matter what direction they're facing. - Consolidated all references to rendertypes into RenderTypes class. - Improved consistency of rendering classes. Methods pass a PoseStack instead of a Matrix4f down the chain where possible so that normals can be calculated, and most rendering classes now fill out all vertex elements so they can be used with any vanilla vertex format. - Rendering methods should prefer to take a VertexConsumer rather than a BufferSource, the caller should provide appropriate buffer as that's where the context for buffer choice is. TODO: - Investigate re-enabling VBOs, and, if not an option, clean up naming and VBO related resource code. * Re-enable vbos Things were extremely slow without them in torture tests. They seem to work fine with Iris. Will need to test with Canvas too. I don't know why that hack with the inverse view rotation uniform works but fog doesn't render correctly without it. Unfortunately, the z-offset method does cause visible artifacts. Background quads can sometimes be seen under the edges of adjacant characters, giving the monitor a stitched together look. Will have to investigate splitting all the background and char quads into two draw calls and using glPolygonOffset on the characters :( which probably means two vbos :( :( Co-authored-by: Toad-Dev <748280+toad-dev@users.noreply.github.com> --- .../client/gui/FixedWidthFontRenderer.java | 100 ++++++++-------- .../computercraft/client/gui/GuiComputer.java | 2 +- .../computercraft/client/gui/GuiPrintout.java | 17 +-- .../client/gui/widgets/WidgetTerminal.java | 6 +- .../client/render/ComputerBorderRenderer.java | 38 +++--- .../client/render/ItemPocketRenderer.java | 44 ++++--- .../client/render/ItemPrintoutRenderer.java | 36 +++--- .../client/render/PrintoutRenderer.java | 42 +++---- .../client/render/RenderTypes.java | 108 +++++------------- .../render/TileEntityMonitorRenderer.java | 69 ++++++----- .../fabric/mixin/MixinGameRenderer.java | 5 - .../integration/ModMenuIntegration.java | 47 +++++++- .../peripheral/monitor/MonitorRenderer.java | 57 +++------ 13 files changed, 278 insertions(+), 293 deletions(-) diff --git a/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java index 5bcb1c935..5e82c7091 100644 --- a/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java +++ b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java @@ -5,8 +5,10 @@ */ package dan200.computercraft.client.gui; +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 dan200.computercraft.client.FrameInfo; import dan200.computercraft.client.render.RenderTypes; @@ -15,7 +17,7 @@ import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.Palette; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.client.renderer.texture.OverlayTexture; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -34,14 +36,10 @@ import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMA * *
  • {@link #drawTerminal}: Draw a terminal with a cursor. This is used by the various computer GUIs to render the * whole term.
  • - *
  • {@link #drawBlocker}: When rendering a terminal using {@link RenderTypes#TERMINAL_WITHOUT_DEPTH} you need to - * render an additional "depth blocker" on top of the monitor.
  • * */ public final class FixedWidthFontRenderer { - public static final ResourceLocation FONT = new ResourceLocation( "computercraft", "textures/gui/term_font.png" ); - public static final int FONT_HEIGHT = 9; public static final int FONT_WIDTH = 6; public static final float WIDTH = 256.0f; @@ -49,6 +47,8 @@ public final class FixedWidthFontRenderer public static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH; public static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH; + public static final float Z_EPSILON = 0.001f; + private FixedWidthFontRenderer() { } @@ -63,7 +63,7 @@ public final class FixedWidthFontRenderer return 15 - Terminal.getColour( c, def ); } - private static void drawChar( Matrix4f transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b, int light ) + private static void drawChar( PoseStack transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b, int light ) { // Short circuit to avoid the common case - the texture should be blank here after all. if( index == '\0' || index == ' ' ) return; @@ -74,25 +74,25 @@ public final class FixedWidthFontRenderer int xStart = 1 + column * (FONT_WIDTH + 2); int yStart = 1 + row * (FONT_HEIGHT + 2); - buffer.vertex( transform, x, y, 0f ).color( r, g, b, 1.0f ).uv( xStart / WIDTH, yStart / WIDTH ).uv2( light ).endVertex(); - buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).uv( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).uv2( light ).endVertex(); - buffer.vertex( transform, x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).uv( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).uv2( light ).endVertex(); - buffer.vertex( transform, x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).uv( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).uv2( light ).endVertex(); - buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).uv( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).uv2( light ).endVertex(); - buffer.vertex( transform, x + FONT_WIDTH, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).uv( (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).uv2( light ).endVertex(); + Matrix4f matrix = transform.last().pose(); + Matrix3f normalMatrix = transform.last().normal(); + vertex( matrix, normalMatrix, buffer, x, y, Z_EPSILON, r, g, b, xStart / WIDTH, yStart / WIDTH, light ); + vertex( matrix, normalMatrix, buffer, x, y + FONT_HEIGHT, Z_EPSILON, r, g, b, xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH, light ); + vertex( matrix, normalMatrix, buffer, x + FONT_WIDTH, y + FONT_HEIGHT, Z_EPSILON, r, g, b, (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH, light ); + vertex( matrix, normalMatrix, buffer, x + FONT_WIDTH, y, Z_EPSILON, r, g, b, (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH, light ); } - private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, float r, float g, float b ) + private static void drawQuad( PoseStack transform, VertexConsumer buffer, float x, float y, float width, float height, float r, float g, float b, int light ) { - buffer.vertex( transform, x, y, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_START ).endVertex(); - buffer.vertex( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_END ).endVertex(); - buffer.vertex( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_START ).endVertex(); - buffer.vertex( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_START ).endVertex(); - buffer.vertex( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_END ).endVertex(); - buffer.vertex( transform, x + width, y + height, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_END ).endVertex(); + Matrix4f matrix = transform.last().pose(); + Matrix3f normalMatrix = transform.last().normal(); + vertex( matrix, normalMatrix, buffer, x, y, 0, r, g, b, BACKGROUND_START, BACKGROUND_START, light ); + vertex( matrix, normalMatrix, buffer, x, y + height, 0, r, g, b, BACKGROUND_START, BACKGROUND_END, light ); + vertex( matrix, normalMatrix, buffer, x + width, y + height, 0, r, g, b, BACKGROUND_END, BACKGROUND_END, light ); + vertex( matrix, normalMatrix, buffer, x + width, y, 0, r, g, b, BACKGROUND_END, BACKGROUND_START, light ); } - private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex ) + private static void drawQuad( PoseStack transform, VertexConsumer buffer, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex, int light ) { double[] colour = palette.getColour( getColour( colourIndex, Colour.BLACK ) ); float r, g, b; @@ -107,23 +107,23 @@ public final class FixedWidthFontRenderer b = (float) colour[2]; } - drawQuad( transform, buffer, x, y, width, height, r, g, b ); + drawQuad( transform, buffer, x, y, width, height, r, g, b, light ); } private static void drawBackground( - @Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y, + @Nonnull PoseStack transform, @Nonnull VertexConsumer buffer, float x, float y, @Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, - float leftMarginSize, float rightMarginSize, float height + float leftMarginSize, float rightMarginSize, float height, int light ) { if( leftMarginSize > 0 ) { - drawQuad( transform, renderer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) ); + drawQuad( transform, buffer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ), light ); } if( rightMarginSize > 0 ) { - drawQuad( transform, renderer, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, greyscale, backgroundColour.charAt( backgroundColour.length() - 1 ) ); + drawQuad( transform, buffer, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, greyscale, backgroundColour.charAt( backgroundColour.length() - 1 ), light ); } // Batch together runs of identical background cells. @@ -136,7 +136,7 @@ public final class FixedWidthFontRenderer if( blockColour != '\0' ) { - drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour ); + drawQuad( transform, buffer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour, light ); } blockColour = colourIndex; @@ -145,19 +145,19 @@ public final class FixedWidthFontRenderer if( blockColour != '\0' ) { - drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, greyscale, blockColour ); + drawQuad( transform, buffer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, greyscale, blockColour, light ); } } public static void drawString( - @Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y, + @Nonnull PoseStack transform, @Nonnull VertexConsumer buffer, float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize, int light ) { if( backgroundColour != null ) { - drawBackground( transform, renderer, x, y, backgroundColour, palette, greyscale, leftMarginSize, rightMarginSize, FONT_HEIGHT ); + drawBackground( transform, buffer, x, y, backgroundColour, palette, greyscale, leftMarginSize, rightMarginSize, FONT_HEIGHT, light ); } for( int i = 0; i < text.length(); i++ ) @@ -178,15 +178,15 @@ public final class FixedWidthFontRenderer // Draw char int index = text.charAt( i ); if( index > 255 ) index = '?'; - drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b, light ); + drawChar( transform, buffer, x + i * FONT_WIDTH, y, index, r, g, b, light ); } } public static void drawTerminalWithoutCursor( - @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, + @Nonnull PoseStack transform, @Nonnull VertexConsumer buffer, 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, int light ) { Palette palette = terminal.getPalette(); @@ -196,13 +196,13 @@ public final class FixedWidthFontRenderer drawBackground( transform, buffer, x, y - topMarginSize, terminal.getBackgroundColourLine( 0 ), palette, greyscale, - leftMarginSize, rightMarginSize, topMarginSize + leftMarginSize, rightMarginSize, topMarginSize, light ); drawBackground( transform, buffer, x, y + height * FONT_HEIGHT, terminal.getBackgroundColourLine( height - 1 ), palette, greyscale, - leftMarginSize, rightMarginSize, bottomMarginSize + leftMarginSize, rightMarginSize, bottomMarginSize, light ); // The main text @@ -217,7 +217,7 @@ public final class FixedWidthFontRenderer } public static void drawCursor( - @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, + @Nonnull PoseStack transform, @Nonnull VertexConsumer buffer, float x, float y, @Nonnull Terminal terminal, boolean greyscale ) { @@ -247,42 +247,44 @@ public final class FixedWidthFontRenderer } public static void drawTerminal( - @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, + @Nonnull PoseStack transform, @Nonnull VertexConsumer buffer, 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, int light ) { - drawTerminalWithoutCursor( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); + drawTerminalWithoutCursor( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize, light ); drawCursor( transform, buffer, x, y, terminal, greyscale ); } - public static void drawTerminal( - @Nonnull Matrix4f transform, float x, float y, @Nonnull Terminal terminal, boolean greyscale, + // Called by WidgetTerminal + public static void drawTerminalImmediate( + @Nonnull PoseStack transform, float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize ) { MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() ); - VertexConsumer buffer = renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ); - drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); + VertexConsumer buffer = renderer.getBuffer( RenderTypes.GUI_TERMINAL ); + drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize, FULL_BRIGHT_LIGHTMAP ); renderer.endBatch(); } - public static void drawEmptyTerminal( @Nonnull Matrix4f transform, @Nonnull MultiBufferSource renderer, float x, float y, float width, float height ) + public static void drawEmptyTerminal( @Nonnull PoseStack transform, @Nonnull VertexConsumer buffer, float x, float y, float width, float height, int light ) { Colour colour = Colour.BLACK; - drawQuad( transform, renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); + drawQuad( transform, buffer, x, y, width, height, colour.getR(), colour.getG(), colour.getB(), light ); } - public static void drawEmptyTerminal( @Nonnull Matrix4f transform, float x, float y, float width, float height ) + public static void drawEmptyTerminalImmediate( @Nonnull PoseStack transform, float x, float y, float width, float height ) { MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() ); - drawEmptyTerminal( transform, renderer, x, y, width, height ); + VertexConsumer buffer = renderer.getBuffer( RenderTypes.GUI_TERMINAL ); + drawEmptyTerminal( transform, buffer, x, y, width, height, FULL_BRIGHT_LIGHTMAP ); renderer.endBatch(); } - public static void drawBlocker( @Nonnull Matrix4f transform, @Nonnull MultiBufferSource renderer, float x, float y, float width, float height ) + private static void vertex( Matrix4f poseMatrix, Matrix3f normalMatrix, VertexConsumer buffer, float x, float y, float z, float r, float g, float b, float u, float v, int light ) { - Colour colour = Colour.BLACK; - drawQuad( transform, renderer.getBuffer( RenderTypes.TERMINAL_BLOCKER ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); + buffer.vertex( poseMatrix, x, y, z ).color( r, g, b, 1.0f ).uv( u, v ).overlayCoords( OverlayTexture.NO_OVERLAY ).uv2( light ).normal( normalMatrix, 0f, 0f, 1f ).endVertex(); } + } diff --git a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java index d05f7e4e1..5eb8cbc8f 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java @@ -76,7 +76,7 @@ public final class GuiComputer extends Computer public void renderBg( @Nonnull PoseStack stack, float partialTicks, int mouseX, int mouseY ) { // Draw a border around the terminal - ComputerBorderRenderer.render( + ComputerBorderRenderer.renderFromGui( ComputerBorderRenderer.getTexture( family ), terminal.x, terminal.y, getBlitOffset(), RenderTypes.FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight() ); diff --git a/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java index ed8e551d5..e5074a941 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java @@ -5,10 +5,10 @@ */ 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 com.mojang.blaze3d.vertex.VertexConsumer; +import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.common.ContainerHeldItem; import dan200.computercraft.shared.media.items.ItemPrintout; @@ -100,13 +100,14 @@ public class GuiPrintout extends AbstractContainerScreen protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY ) { // Draw the printout - RenderSystem.setShaderColor( 1.0f, 1.0f, 1.0f, 1.0f ); - 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 ); + + VertexConsumer borderBuffer = renderer.getBuffer( RenderTypes.GUI_PRINTOUT_BACKGROUND ); + drawBorder( transform, borderBuffer, leftPos, topPos, getBlitOffset(), page, pages, book, FULL_BRIGHT_LIGHTMAP ); + + VertexConsumer textBuffer = renderer.getBuffer( RenderTypes.GUI_PRINTOUT_TEXT ); + drawText( transform, textBuffer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours ); + renderer.endBatch(); } diff --git a/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java index ebef85e1d..bae7fd8fd 100644 --- a/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java +++ b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java @@ -6,7 +6,6 @@ package dan200.computercraft.client.gui.widgets; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Matrix4f; import dan200.computercraft.client.gui.FixedWidthFontRenderer; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.computer.core.ClientComputer; @@ -313,15 +312,14 @@ 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(); if( terminal != null ) { - FixedWidthFontRenderer.drawTerminal( matrix, innerX, innerY, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN ); + FixedWidthFontRenderer.drawTerminalImmediate( transform, innerX, innerY, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN ); } else { - FixedWidthFontRenderer.drawEmptyTerminal( matrix, x, y, width, height ); + FixedWidthFontRenderer.drawEmptyTerminalImmediate( transform, x, y, width, height ); } } diff --git a/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java b/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java index 225211d71..a17f50bc0 100644 --- a/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java @@ -5,13 +5,15 @@ */ package dan200.computercraft.client.render; +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 dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.computer.core.ComputerFamily; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nonnull; @@ -53,13 +55,13 @@ public class ComputerBorderRenderer public static final int TEX_SIZE = 256; private static final float TEX_SCALE = 1 / (float) TEX_SIZE; - private final Matrix4f transform; + private final PoseStack transform; private final VertexConsumer builder; private final int light; private final int z; private final float r, g, b; - public ComputerBorderRenderer( Matrix4f transform, VertexConsumer builder, int z, int light, float r, float g, float b ) + public ComputerBorderRenderer( PoseStack transform, VertexConsumer builder, int z, int light, float r, float g, float b ) { this.transform = transform; this.builder = builder; @@ -86,20 +88,18 @@ public class ComputerBorderRenderer } } - public static RenderType getRenderType( ResourceLocation location ) + public static void renderFromGui( ResourceLocation location, int x, int y, int z, int light, int width, int height ) { - // See note in RenderTypes about why we use text rather than anything intuitive. - return RenderType.text( location ); + PoseStack identityStack = new PoseStack(); + MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() ); + render( + identityStack, renderer.getBuffer( RenderTypes.guiComputerBorder( location ) ), + x, y, z, light, width, height, false, 1, 1, 1 + ); + renderer.endBatch(); } - public static void render( ResourceLocation location, int x, int y, int z, int light, int width, int height ) - { - MultiBufferSource.BufferSource source = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() ); - render( IDENTITY, source.getBuffer( getRenderType( location ) ), x, y, z, light, width, height, false, 1, 1, 1 ); - source.endBatch(); - } - - public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int light, int width, int height, boolean withLight, float r, float g, float b ) + public static void render( PoseStack transform, VertexConsumer buffer, int x, int y, int z, int light, int width, int height, boolean withLight, float r, float g, float b ) { new ComputerBorderRenderer( transform, buffer, z, light, r, g, b ).doRender( x, y, width, height, withLight ); } @@ -151,9 +151,11 @@ public class ComputerBorderRenderer private void renderTexture( int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight ) { - builder.vertex( transform, x, y + height, z ).color( r, g, b, 1.0f ).uv( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).uv2( light ).endVertex(); - builder.vertex( transform, x + width, y + height, z ).color( r, g, b, 1.0f ).uv( (u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).uv2( light ).endVertex(); - builder.vertex( transform, x + width, y, z ).color( r, g, b, 1.0f ).uv( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE ).uv2( light ).endVertex(); - builder.vertex( transform, x, y, z ).color( r, g, b, 1.0f ).uv( u * TEX_SCALE, v * TEX_SCALE ).uv2( light ).endVertex(); + Matrix4f poseMatrix = transform.last().pose(); + Matrix3f normalMatrix = transform.last().normal(); + builder.vertex( poseMatrix, x, y + height, z ).color( r, g, b, 1.0f ).uv( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).overlayCoords( OverlayTexture.NO_OVERLAY ).uv2( light ).normal( normalMatrix, 0f, 0f, 1f ).endVertex(); + builder.vertex( poseMatrix, x + width, y + height, z ).color( r, g, b, 1.0f ).uv( (u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).overlayCoords( OverlayTexture.NO_OVERLAY ).uv2( light ).normal( normalMatrix, 0f, 0f, 1f ).endVertex(); + builder.vertex( poseMatrix, x + width, y, z ).color( r, g, b, 1.0f ).uv( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE ).overlayCoords( OverlayTexture.NO_OVERLAY ).uv2( light ).normal( normalMatrix, 0f, 0f, 1f ).endVertex(); + builder.vertex( poseMatrix, x, y, z ).color( r, g, b, 1.0f ).uv( u * TEX_SCALE, v * TEX_SCALE ).overlayCoords( OverlayTexture.NO_OVERLAY ).uv2( light ).normal( normalMatrix, 0f, 0f, 1f ).endVertex(); } } diff --git a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java index 6806aa089..9ab59b94b 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java @@ -6,6 +6,7 @@ package dan200.computercraft.client.render; import com.mojang.blaze3d.vertex.*; +import com.mojang.math.Matrix3f; import com.mojang.math.Matrix4f; import com.mojang.math.Vector3f; import dan200.computercraft.ComputerCraft; @@ -16,12 +17,13 @@ import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.pocket.items.ItemPocketComputer; import dan200.computercraft.shared.util.Colour; import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; +import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*; import static dan200.computercraft.client.render.ComputerBorderRenderer.*; +import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP; /** * Emulates map rendering for pocket computers. @@ -63,7 +65,9 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer transform.scale( 0.5f, 0.5f, 0.5f ); float scale = 0.75f / Math.max( width + BORDER * 2, height + BORDER * 2 + LIGHT_HEIGHT ); - transform.scale( scale, scale, -1.0f ); + // Avoid PoseStack#scale to preserve normal matrix, and fix the normals ourselves. + transform.last().pose().multiply( Matrix4f.createScaleMatrix( scale, scale, -1.0f ) ); + transform.last().normal().mul( -1.0f ); transform.translate( -0.5 * width, -0.5 * height, 0 ); // Render the main frame @@ -71,31 +75,32 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer ComputerFamily family = item.getFamily(); int frameColour = item.getColour( stack ); - Matrix4f matrix = transform.last().pose(); - renderFrame( matrix, renderer, family, frameColour, light, width, height ); + renderFrame( transform, renderer, family, frameColour, light, width, height ); // Render the light int lightColour = ItemPocketComputer.getLightState( stack ); if( lightColour == -1 ) lightColour = Colour.BLACK.getHex(); - renderLight( matrix, renderer, lightColour, width, height ); + renderLight( transform, renderer, lightColour, width, height ); + VertexConsumer buffer = renderer.getBuffer( RenderTypes.ITEM_POCKET_TERMINAL ); if( computer != null && terminal != null ) { FixedWidthFontRenderer.drawTerminal( - matrix, renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ), - MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN + transform, buffer, + MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN, FULL_BRIGHT_LIGHTMAP ); - FixedWidthFontRenderer.drawBlocker( transform.last().pose(), renderer, 0, 0, width, height ); } else { - FixedWidthFontRenderer.drawEmptyTerminal( matrix, 0, 0, width, height ); + FixedWidthFontRenderer.drawEmptyTerminal( + transform, buffer, + 0, 0, width, height, 0 ); } transform.popPose(); } - private static void renderFrame( Matrix4f transform, MultiBufferSource render, ComputerFamily family, int colour, int light, int width, int height ) + private static void renderFrame( PoseStack transform, MultiBufferSource renderer, ComputerFamily family, int colour, int light, int width, int height ) { ResourceLocation texture = colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family ); @@ -103,20 +108,23 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer float g = ((colour >>> 8) & 0xFF) / 255.0f; float b = (colour & 0xFF) / 255.0f; - ComputerBorderRenderer.render( transform, render.getBuffer( ComputerBorderRenderer.getRenderType( texture ) ), 0, 0, 0, light, width, height, true, r, g, b ); + VertexConsumer buffer = renderer.getBuffer( RenderTypes.itemPocketBorder( texture ) ); + ComputerBorderRenderer.render( transform, buffer, 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 renderer, int colour, int width, int height ) { float r = ((colour >>> 16) & 0xFF) / 255.0f; float g = ((colour >>> 8) & 0xFF) / 255.0f; float b = (colour & 0xFF) / 255.0f; float z = 0.001f; - VertexConsumer buffer = render.getBuffer( RenderTypes.POSITION_COLOR ); - buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex(); - buffer.vertex( transform, width, height + LIGHT_HEIGHT + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex(); - buffer.vertex( transform, width, height + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex(); - buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex(); + VertexConsumer buffer = renderer.getBuffer( RenderTypes.ITEM_POCKET_LIGHT ); + Matrix4f poseMatrix = transform.last().pose(); + Matrix3f normalMatrix = transform.last().normal(); + buffer.vertex( poseMatrix, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_START ).overlayCoords( OverlayTexture.NO_OVERLAY ).uv2( FULL_BRIGHT_LIGHTMAP ).normal( normalMatrix, 0f, 0f, 1f ).endVertex(); + buffer.vertex( poseMatrix, width, height + LIGHT_HEIGHT + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_END ).overlayCoords( OverlayTexture.NO_OVERLAY ).uv2( FULL_BRIGHT_LIGHTMAP ).normal( normalMatrix, 0f, 0f, 1f ).endVertex(); + buffer.vertex( poseMatrix, width, height + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_END ).overlayCoords( OverlayTexture.NO_OVERLAY ).uv2( FULL_BRIGHT_LIGHTMAP ).normal( normalMatrix, 0f, 0f, 1f ).endVertex(); + buffer.vertex( poseMatrix, width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_START ).overlayCoords( OverlayTexture.NO_OVERLAY ).uv2( FULL_BRIGHT_LIGHTMAP ).normal( normalMatrix, 0f, 0f, 1f ).endVertex(); } } diff --git a/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java index 8d07b890c..422370065 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java @@ -29,32 +29,38 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer { } - public boolean renderInFrame( PoseStack matrixStack, MultiBufferSource consumerProvider, ItemStack stack, int light ) + public boolean renderInFrame( PoseStack transform, MultiBufferSource renderer, ItemStack stack, int light ) { if( !(stack.getItem() instanceof ItemPrintout) ) return false; // Move a little bit forward to ensure we're not clipping with the frame - matrixStack.translate( 0.0f, 0.0f, -0.001f ); - matrixStack.mulPose( Vector3f.ZP.rotationDegrees( 180f ) ); - matrixStack.scale( 0.95f, 0.95f, -0.95f ); - matrixStack.translate( -0.5f, -0.5f, 0.0f ); + transform.translate( 0.0f, 0.0f, -0.001f ); + transform.mulPose( Vector3f.ZP.rotationDegrees( 180f ) ); + // Avoid PoseStack#scale to preserve normal matrix, and fix the normals ourselves. + transform.last().pose().multiply( Matrix4f.createScaleMatrix( 0.95f, 0.95f, -0.95f ) ); + transform.last().normal().mul( -1.0f ); - drawPrintout( matrixStack, consumerProvider, stack, light ); + //transform.last().normal().mul( -1.0f ); + transform.translate( -0.5f, -0.5f, 0.0f ); + + drawPrintout( transform, renderer, stack, light ); return true; } @Override - protected void renderItem( PoseStack transform, MultiBufferSource render, ItemStack stack, int light ) + protected void renderItem( PoseStack transform, MultiBufferSource renderer, ItemStack stack, int light ) { transform.mulPose( Vector3f.XP.rotationDegrees( 180f ) ); - transform.scale( 0.42f, 0.42f, -0.42f ); + // Avoid PoseStack#scale to preserve normal matrix, and fix the normals ourselves. + transform.last().pose().multiply( Matrix4f.createScaleMatrix( 0.42f, 0.42f, -0.42f ) ); + transform.last().normal().mul( -1.0f ); transform.translate( -0.5f, -0.48f, 0.0f ); - drawPrintout( transform, render, stack, light ); + drawPrintout( transform, renderer, stack, light ); } - private static void drawPrintout( PoseStack transform, MultiBufferSource render, ItemStack stack, int light ) + private static void drawPrintout( PoseStack transform, MultiBufferSource renderer, ItemStack stack, int light ) { int pages = ItemPrintout.getPageCount( stack ); boolean book = ((ItemPrintout) stack.getItem()).getType() == ItemPrintout.Type.BOOK; @@ -81,11 +87,13 @@ 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, renderer.getBuffer( RenderTypes.ITEM_PRINTOUT_BACKGROUND ), + 0, 0, -0.01f, 0, pages, book, light + ); drawText( - matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, light, - ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) + transform, renderer.getBuffer( RenderTypes.ITEM_PRINTOUT_TEXT ), + X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, light, ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) ); } } diff --git a/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java b/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java index 58bef2984..af35f2253 100644 --- a/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java @@ -5,12 +5,14 @@ */ package dan200.computercraft.client.render; +import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Matrix3f; import com.mojang.math.Matrix4f; import dan200.computercraft.client.gui.FixedWidthFontRenderer; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.util.Palette; -import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.texture.OverlayTexture; import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE; @@ -54,9 +56,8 @@ public final class PrintoutRenderer private PrintoutRenderer() {} - public static void drawText( Matrix4f transform, MultiBufferSource renderer, int x, int y, int start, int light, TextBuffer[] text, TextBuffer[] colours ) + public static void drawText( PoseStack transform, VertexConsumer buffer, int x, int y, int start, int light, TextBuffer[] text, TextBuffer[] colours ) { - VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT ); for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) { FixedWidthFontRenderer.drawString( transform, buffer, @@ -67,9 +68,8 @@ public final class PrintoutRenderer } } - public static void drawText( Matrix4f transform, MultiBufferSource renderer, int x, int y, int start, int light, String[] text, String[] colours ) + public static void drawText( PoseStack transform, VertexConsumer buffer, int x, int y, int start, int light, String[] text, String[] colours ) { - VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT ); for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) { FixedWidthFontRenderer.drawString( transform, buffer, @@ -81,13 +81,11 @@ public final class PrintoutRenderer } } - public static void drawBorder( Matrix4f transform, MultiBufferSource renderer, float x, float y, float z, int page, int pages, boolean isBook, int light ) + public static void drawBorder( PoseStack transform, VertexConsumer buffer, float x, float y, float z, int page, int pages, boolean isBook, int light ) { int leftPages = page; int rightPages = pages - page - 1; - VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_BACKGROUND ); - if( isBook ) { // Border @@ -144,25 +142,29 @@ public final class PrintoutRenderer } } - private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height, int light ) + private static void drawTexture( PoseStack transform, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height, int light ) { - vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + height) / BG_SIZE, light ); - vertex( buffer, matrix, x + width, y + height, z, (u + width) / BG_SIZE, (v + height) / BG_SIZE, light ); - vertex( buffer, matrix, x + width, y, z, (u + width) / BG_SIZE, v / BG_SIZE, light ); - vertex( buffer, matrix, x, y, z, u / BG_SIZE, v / BG_SIZE, light ); + Matrix4f poseMatrix = transform.last().pose(); + Matrix3f normalMatrix = transform.last().normal(); + vertex( poseMatrix, normalMatrix, buffer, x, y + height, z, u / BG_SIZE, (v + height) / BG_SIZE, light ); + vertex( poseMatrix, normalMatrix, buffer, x + width, y + height, z, (u + width) / BG_SIZE, (v + height) / BG_SIZE, light ); + vertex( poseMatrix, normalMatrix, buffer, x + width, y, z, (u + width) / BG_SIZE, v / BG_SIZE, light ); + vertex( poseMatrix, normalMatrix, buffer, x, y, z, u / BG_SIZE, v / BG_SIZE, light ); } - private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float width, float height, float u, float v, float tWidth, float tHeight, int light ) + private static void drawTexture( PoseStack transform, VertexConsumer buffer, float x, float y, float z, float width, float height, float u, float v, float tWidth, float tHeight, int light ) { - vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + tHeight) / BG_SIZE, light ); - vertex( buffer, matrix, x + width, y + height, z, (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE, light ); - vertex( buffer, matrix, x + width, y, z, (u + tWidth) / BG_SIZE, v / BG_SIZE, light ); - vertex( buffer, matrix, x, y, z, u / BG_SIZE, v / BG_SIZE, light ); + Matrix4f poseMatrix = transform.last().pose(); + Matrix3f normalMatrix = transform.last().normal(); + vertex( poseMatrix, normalMatrix, buffer, x, y + height, z, u / BG_SIZE, (v + tHeight) / BG_SIZE, light ); + vertex( poseMatrix, normalMatrix, buffer, x + width, y + height, z, (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE, light ); + vertex( poseMatrix, normalMatrix, buffer, x + width, y, z, (u + tWidth) / BG_SIZE, v / BG_SIZE, light ); + vertex( poseMatrix, normalMatrix, buffer, x, y, z, u / BG_SIZE, v / BG_SIZE, light ); } - private static void vertex( VertexConsumer buffer, Matrix4f matrix, float x, float y, float z, float u, float v, int light ) + private static void vertex( Matrix4f poseMatrix, Matrix3f normalMatrix, VertexConsumer buffer, float x, float y, float z, float u, float v, int light ) { - buffer.vertex( matrix, x, y, z ).color( 255, 255, 255, 255 ).uv( u, v ).uv2( light ).endVertex(); + buffer.vertex( poseMatrix, x, y, z ).color( 255, 255, 255, 255 ).uv( u, v ).overlayCoords( OverlayTexture.NO_OVERLAY ).uv2( light ).normal( normalMatrix, 0f, 0f, 1f ).endVertex(); } public static float offsetAt( int page ) diff --git a/src/main/java/dan200/computercraft/client/render/RenderTypes.java b/src/main/java/dan200/computercraft/client/render/RenderTypes.java index 21d407b6e..57d1d5e32 100644 --- a/src/main/java/dan200/computercraft/client/render/RenderTypes.java +++ b/src/main/java/dan200/computercraft/client/render/RenderTypes.java @@ -7,7 +7,7 @@ package dan200.computercraft.client.render; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexFormat; -import dan200.computercraft.client.gui.FixedWidthFontRenderer; +import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.ShaderInstance; @@ -15,28 +15,41 @@ import net.minecraft.resources.ResourceLocation; import javax.annotation.Nonnull; + public class RenderTypes { + public static final ResourceLocation FONT = new ResourceLocation( "computercraft", "textures/gui/term_font.png" ); + public static final ResourceLocation PRINTOUT_BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/printout.png" ); public static final int FULL_BRIGHT_LIGHTMAP = (0xF << 4) | (0xF << 20); - public static MonitorTextureBufferShader monitorTboShader; - public static ShaderInstance terminalShader; - - public static final RenderType TERMINAL_WITHOUT_DEPTH = Types.TERMINAL_WITHOUT_DEPTH; - public static final RenderType TERMINAL_BLOCKER = Types.TERMINAL_BLOCKER; - public static final RenderType TERMINAL_WITH_DEPTH = Types.TERMINAL_WITH_DEPTH; public static final RenderType MONITOR_TBO = Types.MONITOR_TBO; - public static final RenderType PRINTOUT_TEXT = Types.PRINTOUT_TEXT; + public static final RenderType MONITOR = RenderType.textIntensity( FONT ); - /** - * This looks wrong (it should be POSITION_COLOR_TEX_LIGHTMAP surely!) but the fragment/vertex shader for that - * appear to entirely ignore the lightmap. - * - * Note that vanilla maps do the same, so this isn't unreasonable. - */ - public static final RenderType PRINTOUT_BACKGROUND = RenderType.text( new ResourceLocation( "computercraft", "textures/gui/printout.png" ) ); + public static final RenderType ITEM_POCKET_TERMINAL = RenderType.textIntensity( FONT ); + public static final RenderType ITEM_POCKET_LIGHT = RenderType.textIntensity( FONT ); + public static final RenderType ITEM_PRINTOUT_BACKGROUND = RenderType.entityCutout( PRINTOUT_BACKGROUND ); + public static final RenderType ITEM_PRINTOUT_TEXT = RenderType.entityCutout( FONT ); - public static final RenderType POSITION_COLOR = Types.POSITION_COLOR; + public static final RenderType GUI_TERMINAL = RenderType.text( FONT ); + public static final RenderType GUI_PRINTOUT_BACKGROUND = RenderType.text( PRINTOUT_BACKGROUND ); + public static final RenderType GUI_PRINTOUT_TEXT = RenderType.text( FONT ); + + public static ShaderInstance getMonitorShader() + { + return GameRenderer.getRendertypeTextIntensityShader(); + } + + public static RenderType itemPocketBorder( ResourceLocation location ) + { + return RenderType.entityCutout( location ); + } + + public static RenderType guiComputerBorder( ResourceLocation location ) + { + return RenderType.text( location ); + } + + public static MonitorTextureBufferShader monitorTboShader; @Nonnull static MonitorTextureBufferShader getMonitorTextureBufferShader() @@ -45,22 +58,12 @@ public class RenderTypes return monitorTboShader; } - @Nonnull - static ShaderInstance getTerminalShader() - { - if( terminalShader == null ) throw new NullPointerException( "MonitorTboShader has not been registered" ); - return terminalShader; - } - private static final class Types extends RenderStateShard { private static final RenderStateShard.TextureStateShard TERM_FONT_TEXTURE = new TextureStateShard( - FixedWidthFontRenderer.FONT, + FONT, false, false // blur, minimap ); - private static final VertexFormat TERM_FORMAT = DefaultVertexFormat.POSITION_COLOR_TEX; - private static final VertexFormat.Mode TERM_MODE = VertexFormat.Mode.TRIANGLES; - 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, @@ -68,57 +71,6 @@ public class RenderTypes RenderType.CompositeState.builder() .setTextureState( TERM_FONT_TEXTURE ) .setShaderState( new ShaderStateShard( RenderTypes::getMonitorTextureBufferShader ) ) - .setWriteMaskState( COLOR_WRITE ) - .createCompositeState( false ) - ); - - static final RenderType TERMINAL_WITHOUT_DEPTH = RenderType.create( - "terminal_without_depth", TERM_FORMAT, TERM_MODE, 1024, - false, false, // useDelegate, needsSorting - RenderType.CompositeState.builder() - .setTextureState( TERM_FONT_TEXTURE ) - .setShaderState( TERM_SHADER ) - .setWriteMaskState( COLOR_WRITE ) - .createCompositeState( false ) - ); - - static final RenderType TERMINAL_BLOCKER = RenderType.create( - "terminal_blocker", TERM_FORMAT, TERM_MODE, 256, - false, false, // useDelegate, needsSorting - RenderType.CompositeState.builder() - .setTextureState( TERM_FONT_TEXTURE ) - .setShaderState( TERM_SHADER ) - .setWriteMaskState( DEPTH_WRITE ) - .createCompositeState( false ) - ); - - static final RenderType TERMINAL_WITH_DEPTH = RenderType.create( - "terminal_with_depth", TERM_FORMAT, TERM_MODE, 1024, - false, false, // useDelegate, needsSorting - RenderType.CompositeState.builder() - .setTextureState( TERM_FONT_TEXTURE ) - .setShaderState( TERM_SHADER ) - .createCompositeState( false ) - ); - - /** - * A variant of {@link #TERMINAL_WITH_DEPTH} which uses the lightmap rather than rendering fullbright. - */ - static final RenderType PRINTOUT_TEXT = RenderType.create( - "printout_text", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP, TERM_MODE, 1024, - false, false, // useDelegate, needsSorting - RenderType.CompositeState.builder() - .setTextureState( TERM_FONT_TEXTURE ) - .setShaderState( RenderStateShard.RENDERTYPE_TEXT_SHADER ) - .setLightmapState( RenderStateShard.LIGHTMAP ) - .createCompositeState( false ) - ); - - static final RenderType POSITION_COLOR = RenderType.create( - "position_color", DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS, 128, - false, false, // useDelegate, needsSorting - RenderType.CompositeState.builder() - .setShaderState( POSITION_COLOR_SHADER ) .createCompositeState( false ) ); diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java index 7c71f4a0f..5cc3c97a5 100644 --- a/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java @@ -9,8 +9,8 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.MemoryTracker; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.*; +import com.mojang.math.Matrix3f; import com.mojang.math.Matrix4f; -import com.mojang.math.Transformation; import com.mojang.math.Vector3f; import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.FrameInfo; @@ -23,7 +23,6 @@ import dan200.computercraft.shared.peripheral.monitor.TileMonitor; import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.DirectionUtil; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.core.BlockPos; @@ -36,6 +35,7 @@ import javax.annotation.Nonnull; import java.nio.ByteBuffer; import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*; +import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP; public class TileEntityMonitorRenderer implements BlockEntityRenderer { @@ -43,10 +43,17 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer list, List>> list2 ) throws IOException { - list2.add( Pair.of( new ShaderInstance( - manager, - "terminal", - RenderTypes.TERMINAL_WITHOUT_DEPTH.format() - ), shader -> RenderTypes.terminalShader = shader ) ); list2.add( Pair.of( new MonitorTextureBufferShader( manager, "monitor_tbo", diff --git a/src/main/java/dan200/computercraft/shared/integration/ModMenuIntegration.java b/src/main/java/dan200/computercraft/shared/integration/ModMenuIntegration.java index 0193fe67c..dfb583e3e 100644 --- a/src/main/java/dan200/computercraft/shared/integration/ModMenuIntegration.java +++ b/src/main/java/dan200/computercraft/shared/integration/ModMenuIntegration.java @@ -7,7 +7,6 @@ package dan200.computercraft.shared.integration; import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ModMenuApi; -import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; import dan200.computercraft.shared.util.Config; import me.shedaniel.clothconfig2.api.ConfigBuilder; @@ -33,20 +32,60 @@ public class ModMenuIntegration implements ModMenuApi Config.clientSpec.correct( Config.clientConfig ); Config.sync(); Config.save(); - ComputerCraft.log.info( "Monitor renderer: {}", ComputerCraft.monitorRenderer ); } ); ConfigCategory client = builder.getOrCreateCategory( new TextComponent( "Client" ) ); ConfigEntryBuilder entryBuilder = builder.entryBuilder(); - client.addEntry( entryBuilder.startEnumSelector( new TextComponent( "Monitor Renderer" ), MonitorRenderer.class, ComputerCraft.monitorRenderer ) + client.addEntry( entryBuilder + .startEnumSelector( + new TextComponent( "Monitor Renderer" ), + MonitorRenderer.class, + Config.clientConfig.getEnum( "monitor_renderer", MonitorRenderer.class ) + ) .setDefaultValue( MonitorRenderer.BEST ) .setSaveConsumer( renderer -> Config.clientConfig.set( "monitor_renderer", renderer ) ) - .setTooltip( Component.nullToEmpty( Config.clientConfig.getComment( "monitor_renderer" ) ) ) + .setTooltip( Component.nullToEmpty( rewrapComment( Config.clientConfig.getComment( "monitor_renderer" ) ) ) ) .build() ); return builder.build(); }; } + + private static String rewrapComment( String comment ) + { + String[] words = comment.strip().replaceAll( "[\r\n]", "" ).split( " " ); + + StringBuilder builder = new StringBuilder(); + int lineLength = 0; + for( String word : words ) + { + int wordLength = word.length(); + + if( lineLength + wordLength + 1 > 50 ) + { + builder.append( "\n" ); + lineLength = 0; + builder.append( word ); + lineLength += wordLength; + } + else + { + if( builder.length() == 0 ) + { + builder.append( word ); + lineLength += wordLength; + } + else + { + builder.append( " " ); + builder.append( word ); + lineLength += wordLength + 1; + } + } + } + + return new String( builder ); + } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorRenderer.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorRenderer.java index 18e88f26d..3eac19b1d 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorRenderer.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorRenderer.java @@ -8,7 +8,6 @@ package dan200.computercraft.shared.peripheral.monitor; import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.render.TileEntityMonitorRenderer; import net.fabricmc.loader.api.FabricLoader; -import org.lwjgl.opengl.GL; import javax.annotation.Nonnull; import java.util.Arrays; @@ -49,61 +48,33 @@ public enum MonitorRenderer @Nonnull public static MonitorRenderer current() { - MonitorRenderer current = ComputerCraft.monitorRenderer; - switch( current ) - { - case BEST: - return best(); - case TBO: - checkCapabilities(); - if( !textureBuffer ) - { - ComputerCraft.log.warn( "Texture buffers are not supported on your graphics card. Falling back to default." ); - ComputerCraft.monitorRenderer = BEST; - return best(); - } + if( !initialised ) initialise(); - return TBO; - default: - return current; - } + MonitorRenderer current = ComputerCraft.monitorRenderer; + if( current == BEST ) return best(); + return current; } private static MonitorRenderer best() { - if( !initialised ) + if( shaderMod ) { - checkCapabilities(); - checkForShaderMods(); - if( textureBuffer && shaderMod ) - { - ComputerCraft.log.warn( "Shader mod detected. Enabling VBO renderer for compatibility." ); - } - - initialised = true; + ComputerCraft.log.warn( "Shader mod detected. Enabling VBO monitor renderer for compatibility." ); + return ComputerCraft.monitorRenderer = VBO; } - - return textureBuffer && !shaderMod ? TBO : VBO; + return ComputerCraft.monitorRenderer = TBO; } private static boolean initialised = false; - private static boolean textureBuffer = false; - private static boolean shaderMod = false; - //TODO find out which shader mods do better with VBOs and add them here. - private static List shaderModIds = Arrays.asList( "optifabric" ); + private static boolean shaderMod; + private static final List shaderModIds = Arrays.asList( "iris", "canvas", "optifabric" ); - private static void checkCapabilities() - { - if( initialised ) return; - - textureBuffer = GL.getCapabilities().OpenGL31; - initialised = true; - } - - private static void checkForShaderMods() + private static void initialise() { shaderMod = FabricLoader.getInstance().getAllMods().stream() .map( modContainer -> modContainer.getMetadata().getId() ) - .anyMatch( id -> shaderModIds.contains( id ) ); + .anyMatch( shaderModIds::contains ); + + initialised = true; } }