1
0
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:
Jonathan Coates 2022-07-30 18:46:31 +01:00
commit 34a2e87735
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
15 changed files with 355 additions and 208 deletions

View File

@ -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'

View File

@ -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();
}

View File

@ -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 )
{

View File

@ -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,

View File

@ -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 )
);
}

View File

@ -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,

View File

@ -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 );

View File

@ -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.

View File

@ -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.
}

View File

@ -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();
}
}

View File

@ -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;
}
}
}
}

View File

@ -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 )
{

View File

@ -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;

View File

@ -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

View File

@ -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() }
/**