A fine solution

- Rely on transform matrix for all font vertex position stuffs
- Use a skew matrix for italics
This commit is contained in:
Jozufozu 2024-09-25 22:53:28 -07:00
parent c1bf31856f
commit 8f9c57783b
5 changed files with 39 additions and 62 deletions

View file

@ -9,6 +9,10 @@ import net.minecraft.client.gui.font.glyphs.BakedGlyph;
import net.minecraft.util.FastColor; import net.minecraft.util.FastColor;
public class GlyphInstance extends AbstractInstance { public class GlyphInstance extends AbstractInstance {
// Skew x by 1 - 0.25 * y
// Note that columns are written as rows.
private static final Matrix4f ITALIC_SKEW = new Matrix4f(1, 0, 0, 0, -0.25f, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
public final Matrix4f pose = new Matrix4f(); public final Matrix4f pose = new Matrix4f();
public float u0; public float u0;
@ -16,14 +20,6 @@ public class GlyphInstance extends AbstractInstance {
public float v0; public float v0;
public float v1; public float v1;
public float x0;
public float x1;
public float x2;
public float x3;
public float y0;
public float y1;
public byte red = (byte) 0xFF; public byte red = (byte) 0xFF;
public byte green = (byte) 0xFF; public byte green = (byte) 0xFF;
public byte blue = (byte) 0xFF; public byte blue = (byte) 0xFF;
@ -47,22 +43,26 @@ public class GlyphInstance extends AbstractInstance {
float up = glyphReader.flywheel$up(); float up = glyphReader.flywheel$up();
float down = glyphReader.flywheel$down(); float down = glyphReader.flywheel$down();
float f = x + left; pose.translate(x + left, y + up - 3.0f, 0.0f);
float g = x + right; pose.scale(right - left, down - up, 1.0f);
float h = up - 3.0f;
float j = down - 3.0f;
float k = y + h;
float l = y + j;
float m = italic ? 1.0f - 0.25f * h : 0.0f;
float n = italic ? 1.0f - 0.25f * j : 0.0f;
y0 = k; if (italic) {
y1 = l; pose.mul(ITALIC_SKEW);
}
x0 = f + m; return this;
x1 = f + n; }
x2 = g + n;
x3 = g + m; public GlyphInstance setEffect(BakedGlyph glyph, float x0, float y0, float x1, float y1, float depth) {
var glyphReader = FlwLibLink.INSTANCE.getGlyphExtension(glyph);
u0 = glyphReader.flywheel$u0();
u1 = glyphReader.flywheel$u1();
v0 = glyphReader.flywheel$v0();
v1 = glyphReader.flywheel$v1();
pose.translate(x0, y0, depth);
pose.scale(x1 - x0, y1 - y0, 1.0f);
return this; return this;
} }

View file

@ -107,8 +107,6 @@ public final class InstanceTypes {
.layout(LayoutBuilder.create() .layout(LayoutBuilder.create()
.matrix("pose", FloatRepr.FLOAT, 4) .matrix("pose", FloatRepr.FLOAT, 4)
.vector("u0u1v0v1", FloatRepr.FLOAT, 4) .vector("u0u1v0v1", FloatRepr.FLOAT, 4)
.vector("x", FloatRepr.FLOAT, 4)
.vector("y", FloatRepr.FLOAT, 2)
.vector("color", FloatRepr.UNSIGNED_BYTE, 4) .vector("color", FloatRepr.UNSIGNED_BYTE, 4)
.vector("light", FloatRepr.UNSIGNED_SHORT, 2) .vector("light", FloatRepr.UNSIGNED_SHORT, 2)
.build()) .build())
@ -118,17 +116,11 @@ public final class InstanceTypes {
MemoryUtil.memPutFloat(ptr + 68, instance.u1); MemoryUtil.memPutFloat(ptr + 68, instance.u1);
MemoryUtil.memPutFloat(ptr + 72, instance.v0); MemoryUtil.memPutFloat(ptr + 72, instance.v0);
MemoryUtil.memPutFloat(ptr + 76, instance.v1); MemoryUtil.memPutFloat(ptr + 76, instance.v1);
MemoryUtil.memPutFloat(ptr + 80, instance.x0); MemoryUtil.memPutByte(ptr + 80, instance.red);
MemoryUtil.memPutFloat(ptr + 84, instance.x1); MemoryUtil.memPutByte(ptr + 81, instance.green);
MemoryUtil.memPutFloat(ptr + 88, instance.x2); MemoryUtil.memPutByte(ptr + 82, instance.blue);
MemoryUtil.memPutFloat(ptr + 92, instance.x3); MemoryUtil.memPutByte(ptr + 83, instance.alpha);
MemoryUtil.memPutFloat(ptr + 96, instance.y0); ExtraMemoryOps.put2x16(ptr + 84, instance.light);
MemoryUtil.memPutFloat(ptr + 100, instance.y1);
MemoryUtil.memPutByte(ptr + 104, instance.red);
MemoryUtil.memPutByte(ptr + 105, instance.green);
MemoryUtil.memPutByte(ptr + 106, instance.blue);
MemoryUtil.memPutByte(ptr + 107, instance.alpha);
ExtraMemoryOps.put2x16(ptr + 108, instance.light);
}) })
.vertexShader(Flywheel.rl("instance/glyph.vert")) .vertexShader(Flywheel.rl("instance/glyph.vert"))
.cullShader(Flywheel.rl("instance/cull/glyph.glsl")) .cullShader(Flywheel.rl("instance/cull/glyph.glsl"))

View file

@ -39,6 +39,8 @@ import net.minecraft.util.FormattedCharSink;
* A visual that renders a single line of text. * A visual that renders a single line of text.
*/ */
public class TextVisual { public class TextVisual {
public static final float ONE_PIXEL = 0.125f;
public boolean dropShadow; public boolean dropShadow;
public boolean with8xOutline; public boolean with8xOutline;
public int backgroundColor = 0; public int backgroundColor = 0;
@ -120,9 +122,9 @@ public class TextVisual {
GlyphInstance glyph = recycler.get(new GlyphModelKey(glyphExtension.flywheel$texture(), new GlyphSettings(bold, dropShadow, with8xOutline))); GlyphInstance glyph = recycler.get(new GlyphModelKey(glyphExtension.flywheel$texture(), new GlyphSettings(bold, dropShadow, with8xOutline)));
glyph.pose.set(pose);
glyph.setGlyph(bakedGlyph, this.x, this.y, style.isItalic()); glyph.setGlyph(bakedGlyph, this.x, this.y, style.isItalic());
glyph.color(r, g, b, this.a); glyph.color(r, g, b, this.a);
glyph.pose.set(pose);
glyph.light = light; glyph.light = light;
glyph.setChanged(); glyph.setChanged();
} }
@ -146,20 +148,9 @@ public class TextVisual {
GlyphInstance glyph = recycler.get(new GlyphModelKey(glyphExtension.flywheel$texture(), new GlyphSettings(false, dropShadow, with8xOutline))); GlyphInstance glyph = recycler.get(new GlyphModelKey(glyphExtension.flywheel$texture(), new GlyphSettings(false, dropShadow, with8xOutline)));
glyph.u0 = glyphExtension.flywheel$u0();
glyph.u1 = glyphExtension.flywheel$u1();
glyph.v0 = glyphExtension.flywheel$v0();
glyph.v1 = glyphExtension.flywheel$v1();
glyph.y0 = y0;
glyph.y1 = y1;
glyph.x0 = x0;
glyph.x1 = x1;
glyph.x2 = x1;
glyph.x3 = x0;
glyph.color(r, g, b, this.a);
glyph.pose.set(pose); glyph.pose.set(pose);
glyph.setEffect(bakedGlyph, x0, y0, x1, y1, depth);
glyph.color(r, g, b, this.a);
glyph.light = light; glyph.light = light;
glyph.setChanged(); glyph.setChanged();
} }
@ -181,7 +172,6 @@ public class TextVisual {
private static final Material GLYPH_MATERIAL = SimpleMaterial.builder() private static final Material GLYPH_MATERIAL = SimpleMaterial.builder()
.cutout(CutoutShaders.ONE_TENTH) .cutout(CutoutShaders.ONE_TENTH)
.backfaceCulling(false)
.build(); .build();
private record GlyphModelKey(ResourceLocation font, GlyphSettings settings) { private record GlyphModelKey(ResourceLocation font, GlyphSettings settings) {
@ -207,7 +197,7 @@ public class TextVisual {
continue; continue;
} }
out.add(new Vector3f(x, y, 0)); out.add(new Vector3f(x * ONE_PIXEL, y * ONE_PIXEL, 0));
} }
} }
} else { } else {
@ -215,11 +205,11 @@ public class TextVisual {
} }
if (bold) { if (bold) {
out.add(new Vector3f(1, 0, 0)); out.add(new Vector3f(ONE_PIXEL, 0, 0));
} }
if (dropShadow) { if (dropShadow) {
out.add(new Vector3f(1, 1, 0)); out.add(new Vector3f(ONE_PIXEL, ONE_PIXEL, 0));
} }
return new GlyphMesh(out.toArray(new Vector3f[0])); return new GlyphMesh(out.toArray(new Vector3f[0]));
@ -232,6 +222,8 @@ public class TextVisual {
* @param quads Each quad will be expanded into 4 vertices. * @param quads Each quad will be expanded into 4 vertices.
*/ */
private record GlyphMesh(Vector3f[] quads) implements QuadMesh { private record GlyphMesh(Vector3f[] quads) implements QuadMesh {
private static final float[] X = new float[]{0, 0, 1, 1};
private static final float[] Y = new float[]{0, 1, 1, 0};
@Override @Override
public int vertexCount() { public int vertexCount() {
@ -245,8 +237,8 @@ public class TextVisual {
var quadStart = i * 4; var quadStart = i * 4;
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
vertexList.x(quadStart + j, quad.x); vertexList.x(quadStart + j, quad.x + X[j]);
vertexList.y(quadStart + j, quad.y); vertexList.y(quadStart + j, quad.y + Y[j]);
vertexList.z(quadStart + j, quad.z); vertexList.z(quadStart + j, quad.z);
vertexList.normalX(quadStart + j, 0); vertexList.normalX(quadStart + j, 0);
vertexList.normalY(quadStart + j, 0); vertexList.normalY(quadStart + j, 0);

View file

@ -1,9 +1,5 @@
#include "flywheel:util/matrix.glsl" #include "flywheel:util/matrix.glsl"
void flw_transformBoundingSphere(in FlwInstance i, inout vec3 center, inout float radius) { void flw_transformBoundingSphere(in FlwInstance i, inout vec3 center, inout float radius) {
radius += abs(i.x[2] - i.x[0]) + abs(i.y[1] - i.y[0]);
center += vec3((i.x[0] + i.x[2]) * 0.5, (i.y[0] + i.y[1]) * 0.5, 0.);
transformBoundingSphere(i.pose, center, radius); transformBoundingSphere(i.pose, center, radius);
} }

View file

@ -3,9 +3,6 @@ void flw_instanceVertex(in FlwInstance i) {
uint yIndex = ((vertexInGlyph + 1u) >> 1u) & 1u; uint yIndex = ((vertexInGlyph + 1u) >> 1u) & 1u;
flw_vertexPos.x += i.x[vertexInGlyph];
flw_vertexPos.y += i.y[yIndex];
flw_vertexPos = i.pose * flw_vertexPos; flw_vertexPos = i.pose * flw_vertexPos;
flw_vertexTexCoord.s = i.u0u1v0v1[(vertexInGlyph & 2u) >> 1u]; flw_vertexTexCoord.s = i.u0u1v0v1[(vertexInGlyph & 2u) >> 1u];