GPU-based font rendering (keming edition)
This commit is contained in:
@@ -3,15 +3,17 @@ import "includes/structs";
|
||||
struct Varyings {
|
||||
float4 positionCS : SV_Position;
|
||||
nointerpolation uint instance;
|
||||
float2 texCoordEM : U_TEXCOORD;
|
||||
float2 texCoordEM;
|
||||
}
|
||||
|
||||
struct GuiText {
|
||||
float4 color;
|
||||
// Index into _GlyphData
|
||||
uint glyph;
|
||||
float2 bottomLeftSSPX;
|
||||
float fontSizePX;
|
||||
// Index into _GlyphData[font]
|
||||
uint16_t glyph;
|
||||
// Index into _GlyphData, _ControlPoints and _BandData
|
||||
uint16_t font;
|
||||
}
|
||||
|
||||
struct GlyphData {
|
||||
@@ -28,10 +30,9 @@ struct GlyphData {
|
||||
|
||||
[[vk::binding(0, 0)]] ConstantBuffer<GlobalUniforms> _Global;
|
||||
[[vk::binding(1, 0)]] StructuredBuffer<GuiText> _Instances;
|
||||
|
||||
[[vk::binding(0, 1)]] StructuredBuffer<GlyphData> _GlyphData;
|
||||
[[vk::binding(1, 1)]] StructuredBuffer<half2> _ControlPoints;
|
||||
[[vk::binding(2, 1)]] StructuredBuffer<uint> _BandData;
|
||||
[[vk::binding(2, 0)]] StructuredBuffer<GlyphData> _GlyphData[];
|
||||
[[vk::binding(3, 0)]] StructuredBuffer<half2> _ControlPoints[];
|
||||
[[vk::binding(4, 0)]] StructuredBuffer<uint> _BandData[];
|
||||
|
||||
static const float2 VERTICES[4] = {
|
||||
float2(0, 1),
|
||||
@@ -70,7 +71,7 @@ uint classifyQuadCurve(float y0, float y1, float y2)
|
||||
let class = (sign0 << 0) | (sign1 << 1) | (sign2 << 2);
|
||||
let shift = 2 * class;
|
||||
|
||||
return (0x2E74U >> shift) & 0b11U;
|
||||
return (0x1DB8 >> shift) & 0b11U;
|
||||
}
|
||||
|
||||
// Find intersections between a quadratic Bézier curve and `y = 0` line by
|
||||
@@ -156,12 +157,12 @@ Varyings vertexMain(uint vertexID : SV_VulkanVertexID, uint instanceID : SV_Vulk
|
||||
|
||||
let vertex = VERTICES[vertexID];
|
||||
let instance = _Instances[instanceID];
|
||||
let glyph = _GlyphData[instance.glyph];
|
||||
let glyph = _GlyphData[instance.font][instance.glyph];
|
||||
let normal = 2.0 * vertex - 1.0;
|
||||
|
||||
let sizePX = instance.fontSizePX * glyph.sizeEM;
|
||||
|
||||
let positionSSPX = vertex * sizePX + instance.bottomLeftSSPX;
|
||||
let positionSSPX = vertex * float2(sizePX.x, -sizePX.y) + instance.bottomLeftSSPX;
|
||||
let dilatedPositionSSPX = positionSSPX + 0.5 * normal;
|
||||
let dilatedPositionCS = float4(mul(_Global.matrixSSPXtoCS, float3(positionSSPX, 1.0)), 0.0, 1.0);
|
||||
|
||||
@@ -177,7 +178,9 @@ Varyings vertexMain(uint vertexID : SV_VulkanVertexID, uint instanceID : SV_Vulk
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(Varyings frag) : SV_Target {
|
||||
let instance = _Instances[frag.instance];
|
||||
let glyph = _GlyphData[instance.glyph];
|
||||
let glyph = _GlyphData[instance.font][instance.glyph];
|
||||
let bandData = _BandData[instance.font];
|
||||
let controlPoints = _ControlPoints[instance.font];
|
||||
|
||||
let emPerPX = fwidth(frag.texCoordEM);
|
||||
let pxPerEM = 1.0 / emPerPX;
|
||||
@@ -191,17 +194,17 @@ float4 fragmentMain(Varyings frag) : SV_Target {
|
||||
var xWeight = 0.0;
|
||||
|
||||
let horizontalBandPtr = glyph.bandPtr.y + band.y;
|
||||
let horizontalBandData = _BandData[horizontalBandPtr];
|
||||
let horizontalBandData = bandData[horizontalBandPtr];
|
||||
let horizontalBandCurvePtr = horizontalBandPtr + (horizontalBandData >> 16);
|
||||
let horizontalBandCurveCount = horizontalBandData & 0xFFFF;
|
||||
|
||||
for (uint horizontalBandCurveID = 0; horizontalBandCurveID < horizontalBandCurveCount; horizontalBandCurveID++) {
|
||||
let cpPtr = _BandData[horizontalBandCurvePtr + horizontalBandCurveID];
|
||||
let cp0 = float2(_ControlPoints[cpPtr]) - frag.texCoordEM;
|
||||
let cp1 = float2(_ControlPoints[cpPtr + 1]) - frag.texCoordEM;
|
||||
let cp2 = float2(_ControlPoints[cpPtr + 2]) - frag.texCoordEM;
|
||||
let cpPtr = bandData[horizontalBandCurvePtr + horizontalBandCurveID];
|
||||
let cp0 = float2(controlPoints[cpPtr + 0]) - frag.texCoordEM;
|
||||
let cp1 = float2(controlPoints[cpPtr + 1]) - frag.texCoordEM;
|
||||
let cp2 = float2(controlPoints[cpPtr + 2]) - frag.texCoordEM;
|
||||
|
||||
if (max(max(cp0.x, cp1.x), cp2.x) * pxPerEM.x < -0.5) break;
|
||||
if (max(max(cp0.x, cp1.x), cp2.x) * pxPerEM.x < -0.5) break; // XXX
|
||||
|
||||
let rootFlags = classifyQuadCurve(cp0.y, cp1.y, cp2.y);
|
||||
if (rootFlags != 0U) {
|
||||
@@ -228,17 +231,17 @@ float4 fragmentMain(Varyings frag) : SV_Target {
|
||||
var yWeight = 0.0;
|
||||
|
||||
let verticalBandPtr = glyph.bandPtr.x + band.x;
|
||||
let verticalBandData = _BandData[verticalBandPtr];
|
||||
let verticalBandData = bandData[verticalBandPtr];
|
||||
let verticalBandCurvePtr = verticalBandPtr + (verticalBandData >> 16);
|
||||
let verticalBandCurveCount = verticalBandData & 0xFFFF;
|
||||
|
||||
for (uint verticalBandCurveID = 0; verticalBandCurveID < verticalBandCurveCount; verticalBandCurveID++) {
|
||||
let cpPtr = _BandData[verticalBandCurvePtr + verticalBandCurveID];
|
||||
let cp0 = float2(_ControlPoints[cpPtr]) - frag.texCoordEM;
|
||||
let cp1 = float2(_ControlPoints[cpPtr + 1]) - frag.texCoordEM;
|
||||
let cp2 = float2(_ControlPoints[cpPtr + 2]) - frag.texCoordEM;
|
||||
let cpPtr = bandData[verticalBandCurvePtr + verticalBandCurveID];
|
||||
let cp0 = float2(controlPoints[cpPtr + 0]) - frag.texCoordEM;
|
||||
let cp1 = float2(controlPoints[cpPtr + 1]) - frag.texCoordEM;
|
||||
let cp2 = float2(controlPoints[cpPtr + 2]) - frag.texCoordEM;
|
||||
|
||||
if (max(max(cp0.y, cp1.y), cp2.y) * pxPerEM.y < -0.5) break;
|
||||
if (max(max(cp0.y, cp1.y), cp2.y) * pxPerEM.y < -0.5) break; // XXX
|
||||
|
||||
let rootFlags = classifyQuadCurve(cp0.x, cp1.x, cp2.x);
|
||||
if (rootFlags != 0U) {
|
||||
|
||||
Reference in New Issue
Block a user