mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-14 20:20:30 +00:00
Merge branch 'mc-1.18.x' into mc-1.19.x
This commit is contained in:
commit
34a2e87735
@ -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() }
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user