monitor rendering and more

This commit is contained in:
cvrunmin 2023-07-09 17:45:13 +08:00
parent 71a4ac22ee
commit a07a1b0152
8 changed files with 68 additions and 32 deletions

View File

@ -17,6 +17,7 @@
import dan200.computercraft.client.render.RenderTypes;
import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer;
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
import dan200.computercraft.client.render.text.TerminalFont;
import dan200.computercraft.client.render.vbo.DirectBuffers;
import dan200.computercraft.client.render.vbo.DirectVertexBuffer;
import dan200.computercraft.core.terminal.Terminal;
@ -124,7 +125,7 @@ public void render(MonitorBlockEntity monitor, float partialTicks, PoseStack tra
transform.popPose();
} else {
FixedWidthFontRenderer.drawEmptyTerminal(
FixedWidthFontRenderer.toVertexConsumer(transform, bufferSource.getBuffer(RenderTypes.TERMINAL)),
FixedWidthFontRenderer.toVertexConsumer(transform, bufferSource.getBuffer(RenderTypes.TERMINAL_FULLTEXT)),
-MARGIN, MARGIN,
(float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2)
);
@ -140,7 +141,8 @@ private static void renderTerminal(
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
var renderType = currentRenderer();
var redraw = monitor.pollTerminalChanged();
var redraw = monitor.pollTerminalChanged()
|| renderState.lastFontTextureSize != TerminalFont.getInstance().getTextureSize(); // need to recalculate uv coordinate
if (renderState.createBuffer(renderType)) redraw = true;
switch (renderType) {
@ -176,6 +178,9 @@ private static void renderTerminal(
var backgroundBuffer = assertNonNull(renderState.backgroundBuffer);
var foregroundBuffer = assertNonNull(renderState.foregroundBuffer);
if (redraw) {
for (int i = 0; i < terminal.getHeight(); i++) {
TerminalFont.getInstance().preloadCharacterFont(terminal.getLine(i));
}
var size = DirectFixedWidthFontRenderer.getVertexCount(terminal);
// In an ideal world we could upload these both into one buffer. However, we can't render VBOs with
@ -198,7 +203,7 @@ private static void renderTerminal(
var oldInverseRotation = RenderSystem.getInverseViewRotationMatrix();
RenderSystem.setInverseViewRotationMatrix(IDENTITY_NORMAL);
RenderTypes.TERMINAL.setupRenderState();
RenderTypes.TERMINAL_FULLTEXT.setupRenderState();
// Render background geometry
backgroundBuffer.bind();
@ -220,13 +225,14 @@ private static void renderTerminal(
// Clear state
RenderSystem.polygonOffset(0.0f, -0.0f);
RenderSystem.disablePolygonOffset();
RenderTypes.TERMINAL.clearRenderState();
RenderTypes.TERMINAL_FULLTEXT.clearRenderState();
VertexBuffer.unbind();
RenderSystem.setInverseViewRotationMatrix(oldInverseRotation);
}
case BEST -> throw new IllegalStateException("Impossible: Should never use BEST renderer");
}
renderState.lastFontTextureSize = TerminalFont.getInstance().getTextureSize();
}
private static void renderToBuffer(DirectVertexBuffer vbo, int size, Consumer<DirectFixedWidthFontRenderer.QuadEmitter> draw) {
@ -235,7 +241,7 @@ private static void renderToBuffer(DirectVertexBuffer vbo, int size, Consumer<Di
draw.accept(sink);
buffer.flip();
vbo.upload(buffer.limit() / sink.format().getVertexSize(), RenderTypes.TERMINAL.mode(), sink.format(), buffer);
vbo.upload(buffer.limit() / sink.format().getVertexSize(), RenderTypes.TERMINAL_FULLTEXT.mode(), sink.format(), buffer);
}
private static void tboVertex(VertexConsumer builder, Matrix4f matrix, float x, float y) {

View File

@ -32,6 +32,7 @@ public class MonitorRenderState implements ClientMonitor.RenderState {
private static final Set<MonitorRenderState> allMonitors = new HashSet<>();
public long lastRenderFrame = -1;
public int lastFontTextureSize = -1;
public @Nullable BlockPos lastRenderPos = null;
public int tboBuffer;

View File

@ -45,21 +45,17 @@ private static void drawChar(QuadEmitter emitter, float x, float y, int index, b
// Short circuit to avoid the common case - the texture should be blank here after all.
if (index == '\0' || index == ' ') return;
var column = index % 16;
var row = index / 16;
var xStart = 1 + column * (FONT_WIDTH + 2);
var yStart = 1 + row * (FONT_HEIGHT + 2);
var glyphUv = TerminalFont.getInstance().getGlyphUv(index);
quad(
emitter, x, y, x + FONT_WIDTH, y + FONT_HEIGHT, 0, colour,
xStart / WIDTH, yStart / WIDTH, (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH
glyphUv.x(), glyphUv.y(), glyphUv.z(), glyphUv.w()
);
}
private static void drawQuad(QuadEmitter emitter, float x, float y, float width, float height, Palette palette, char colourIndex) {
var colour = palette.getRenderColours(getColour(colourIndex, Colour.BLACK));
quad(emitter, x, y, x + width, y + height, 0f, colour, BACKGROUND_START, BACKGROUND_START, BACKGROUND_END, BACKGROUND_END);
var glyphUv = TerminalFont.getInstance().getWhiteGlyphUv();
quad(emitter, x, y, x + width, y + height, 0f, colour, glyphUv.x(), glyphUv.y(), glyphUv.z(), glyphUv.w());
}
private static void drawBackground(
@ -99,7 +95,7 @@ public static void drawString(QuadEmitter emitter, float x, float y, TextBuffer
var colour = palette.getRenderColours(getColour(textColour.charAt(i), Colour.BLACK));
int index = text.charAt(i);
if (index > 255) index = '?';
// if (index > 255) index = '?';
drawChar(emitter, x + i * FONT_WIDTH, y, index, colour);
}

View File

@ -24,6 +24,7 @@
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
public class DynamicFontTexture extends AbstractTexture {
@ -117,17 +118,20 @@ void registeredGlyph(int codepoint, GlyphInfo glyphInfo){
private RegisteredGlyph registerGlyph(GlyphInfo glyphInfo) {
var regGlyphWrapper = new RegisteredGlyph[]{ null };
glyphInfo.bake(sheetGlyphInfo -> {
var assignedNode = rootNode.insert(sheetGlyphInfo);
var offsetX = ((int) glyphInfo.getAdvance());
offsetX = offsetX + sheetGlyphInfo.getPixelWidth() <= 16 ? offsetX : 0;
var wrapper = new SheetGlyphInfoWrapper(sheetGlyphInfo, Optional.of(offsetX));
var assignedNode = rootNode.insert(wrapper);
if (assignedNode == null) {
resize(currentSize * 2);
assignedNode = rootNode.insert(sheetGlyphInfo);
assignedNode = rootNode.insert(wrapper);
}
if (assignedNode == null) {
return null;
}
bind();
sheetGlyphInfo.upload(assignedNode.x, assignedNode.y);
regGlyphWrapper[0] = new RegisteredGlyph(assignedNode.x, assignedNode.y, assignedNode.x + sheetGlyphInfo.getPixelWidth(), assignedNode.y + sheetGlyphInfo.getPixelHeight());
sheetGlyphInfo.upload(assignedNode.x + offsetX / 2, assignedNode.y);
regGlyphWrapper[0] = new RegisteredGlyph(assignedNode.x, assignedNode.y, assignedNode.x + sheetGlyphInfo.getPixelWidth() + offsetX, assignedNode.y + sheetGlyphInfo.getPixelHeight());
return null;
});
return regGlyphWrapper[0];
@ -254,4 +258,40 @@ else if(glyphW > halfSize){
public record RegisteredGlyph (float u0, float v0, float u1, float v1){
}
static class SheetGlyphInfoWrapper implements SheetGlyphInfo{
private final SheetGlyphInfo backend;
private final Optional<Integer> optOffsetX;
SheetGlyphInfoWrapper(SheetGlyphInfo backend, Optional<Integer> optOffsetX){
this.backend = backend;
this.optOffsetX = optOffsetX;
}
@Override
public int getPixelWidth() {
return optOffsetX.orElse(0) + backend.getPixelWidth();
}
@Override
public int getPixelHeight() {
return backend.getPixelHeight();
}
@Override
public void upload(int i, int i1) {
backend.upload(i, i1);
}
@Override
public boolean isColored() {
return backend.isColored();
}
@Override
public float getOversample() {
return backend.getOversample();
}
}
}

View File

@ -70,19 +70,6 @@ private static void drawChar(QuadEmitter emitter, float x, float y, int index, b
emitter, x, y, x + FONT_WIDTH, y + FONT_HEIGHT, 0, colour,
glyphUv.x(), glyphUv.y(), glyphUv.z(), glyphUv.w(), light
);
if(false)
{
var column = index % 16;
var row = index / 16;
var xStart = 1 + column * (FONT_WIDTH + 2);
var yStart = 1 + row * (FONT_HEIGHT + 2);
quad(
emitter, x, y, x + FONT_WIDTH, y + FONT_HEIGHT, 0, colour,
xStart / WIDTH, yStart / WIDTH, (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH, light
);
}
}
public static void drawQuad(QuadEmitter emitter, float x, float y, float z, float width, float height, byte[] colour, int light) {

View File

@ -50,6 +50,10 @@ private TerminalFont(){
}
}
public int getTextureSize(){
return fullTexture.getCurrentSize();
}
public Vector4f getGlyphUv(int codepoint){
var registeredGlyph = this.fullTexture.getGlyph(codepoint);
return new Vector4f(registeredGlyph.u0() / this.fullTexture.getCurrentSize(),

View File

@ -226,6 +226,7 @@ local function readutf8(_sReplaceChar, _tHistory, _fnComplete, _sDefault)
elseif sEvent == "pasteutf" then
-- Pasted text
clear()
param = utflib.UTFString(param)
sLine = sLine:sub(1, nPos) .. param .. sLine:sub(nPos + 1)
nPos = nPos + #param
recomplete()

View File

@ -42,6 +42,7 @@ print("Call exit() to exit.")
term.setTextColour(colours.white)
local unicodeMode = settings.get("lua.unicode")
local ulib = require("cc.utflib")
local write, print, printError, read
if unicodeMode then
local uterm = require("cc.utflib.term")
@ -82,7 +83,7 @@ while running do
end
local name, offset = "=lua[" .. chunk_idx .. "]", 0
if ulib.isUTFString(input) then input = tostring(input) end
local func, err = load(input, name, "t", tEnv)
if load("return " .. input) then
-- We wrap the expression with a call to _echo(...), which prevents tail