Font builder
Some checks failed
CI / React UI Build (push) Successful in 10s
CI / Native Windows Build And Tests (push) Failing after 2m10s
CI / Windows Release Package (push) Has been skipped

This commit is contained in:
2026-05-20 15:49:29 +10:00
parent f589b1e1fe
commit 081364e764
13 changed files with 476 additions and 33 deletions

View File

@@ -63,6 +63,11 @@ float grainScalar(float2 uv)
return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453);
}
float4 sampleVhsFrame(float2 uv)
{
return sampleVideo(saturate(uv));
}
float3 animatedChromaGrain(float2 uv, float time, float2 outputResolution, float grainSize)
{
float safeGrainSize = max(grainSize, 0.001);
@@ -142,15 +147,15 @@ float3 softBloom(float2 uv, float2 outputResolution, float radius)
float2 dx = float2(pixel.x * radius, 0.0);
float2 dy = float2(0.0, pixel.y * radius);
float3 sum = sampleVideo(frac(uv)).rgb * 0.28;
sum += sampleVideo(frac(uv + dx)).rgb * 0.14;
sum += sampleVideo(frac(uv - dx)).rgb * 0.14;
sum += sampleVideo(frac(uv + dy)).rgb * 0.14;
sum += sampleVideo(frac(uv - dy)).rgb * 0.14;
sum += sampleVideo(frac(uv + dx + dy)).rgb * 0.075;
sum += sampleVideo(frac(uv + dx - dy)).rgb * 0.075;
sum += sampleVideo(frac(uv - dx + dy)).rgb * 0.075;
sum += sampleVideo(frac(uv - dx - dy)).rgb * 0.075;
float3 sum = sampleVhsFrame(uv).rgb * 0.28;
sum += sampleVhsFrame(uv + dx).rgb * 0.14;
sum += sampleVhsFrame(uv - dx).rgb * 0.14;
sum += sampleVhsFrame(uv + dy).rgb * 0.14;
sum += sampleVhsFrame(uv - dy).rgb * 0.14;
sum += sampleVhsFrame(uv + dx + dy).rgb * 0.075;
sum += sampleVhsFrame(uv + dx - dy).rgb * 0.075;
sum += sampleVhsFrame(uv - dx + dy).rgb * 0.075;
sum += sampleVhsFrame(uv - dx - dy).rgb * 0.075;
return sum;
}
@@ -158,11 +163,11 @@ float3 softCrossBlur(float2 uv, float2 outputResolution, float radius)
{
float2 pixel = 1.0 / max(outputResolution, float2(1.0, 1.0));
float2 offset = pixel * radius;
float3 sum = sampleVideo(frac(uv)).rgb * 0.40;
sum += sampleVideo(frac(uv + float2(offset.x, 0.0))).rgb * 0.15;
sum += sampleVideo(frac(uv - float2(offset.x, 0.0))).rgb * 0.15;
sum += sampleVideo(frac(uv + float2(0.0, offset.y))).rgb * 0.15;
sum += sampleVideo(frac(uv - float2(0.0, offset.y))).rgb * 0.15;
float3 sum = sampleVhsFrame(uv).rgb * 0.40;
sum += sampleVhsFrame(uv + float2(offset.x, 0.0)).rgb * 0.15;
sum += sampleVhsFrame(uv - float2(offset.x, 0.0)).rgb * 0.15;
sum += sampleVhsFrame(uv + float2(0.0, offset.y)).rgb * 0.15;
sum += sampleVhsFrame(uv - float2(0.0, offset.y)).rgb * 0.15;
return sum;
}
@@ -174,14 +179,14 @@ float3 applyChromaCrawl(float3 color, float2 uv, float time, float2 outputResolu
float2 pixel = 1.0 / max(outputResolution, float2(1.0, 1.0));
float lumaCenter = dot(color, float3(0.299, 0.587, 0.114));
float lumaX = dot(sampleVideo(frac(uv + float2(pixel.x, 0.0))).rgb, float3(0.299, 0.587, 0.114));
float lumaY = dot(sampleVideo(frac(uv + float2(0.0, pixel.y))).rgb, float3(0.299, 0.587, 0.114));
float lumaX = dot(sampleVhsFrame(uv + float2(pixel.x, 0.0)).rgb, float3(0.299, 0.587, 0.114));
float lumaY = dot(sampleVhsFrame(uv + float2(0.0, pixel.y)).rgb, float3(0.299, 0.587, 0.114));
float edge = saturate((abs(lumaX - lumaCenter) + abs(lumaY - lumaCenter)) * 6.0);
float phase = sin(uv.y * outputResolution.y * 1.35 + time * 36.0) * cos(uv.x * outputResolution.x * 0.55 - time * 21.0);
float2 crawlOffset = float2(phase, -phase * 0.35) * pixel * (1.0 + amount * 8.0);
float3 shiftedA = sampleVideo(frac(uv + crawlOffset)).rgb;
float3 shiftedB = sampleVideo(frac(uv - crawlOffset * 0.75)).rgb;
float3 shiftedA = sampleVhsFrame(uv + crawlOffset).rgb;
float3 shiftedB = sampleVhsFrame(uv - crawlOffset * 0.75).rgb;
float3 crawled = color;
crawled.r = lerp(color.r, shiftedA.r, edge * amount);
crawled.b = lerp(color.b, shiftedB.b, edge * amount);
@@ -249,7 +254,7 @@ float3 blurVhs(float2 uv, float d, int sampleCount)
break;
float2 offset = circle(start, float(sampleCount), float(i)) * scale;
sum += sampleVideo(frac(uv + offset)).rgb * weight;
sum += sampleVhsFrame(uv + offset).rgb * weight;
}
return sum;
@@ -299,23 +304,23 @@ float4 buildTapeSmear(ShaderContext context)
float4 finishVhs(ShaderContext context)
{
float time = distortedTapeTime(context);
float3 color = sampleVideo(context.uv).rgb;
float3 color = sampleVhsFrame(context.uv).rgb;
// Radial red/blue offsets create lens and deck misregistration before the
// wider tape effects are layered in.
float2 centered = context.uv * 2.0 - 1.0;
centered.x *= context.outputResolution.x / max(context.outputResolution.y, 1.0);
float2 aberrationOffset = centered * (aberrationAmount * 0.0015);
float redAberration = sampleVideo(frac(context.uv + aberrationOffset)).r;
float blueAberration = sampleVideo(frac(context.uv - aberrationOffset)).b;
float redAberration = sampleVhsFrame(context.uv + aberrationOffset).r;
float blueAberration = sampleVhsFrame(context.uv - aberrationOffset).b;
color.r = lerp(color.r, redAberration, 0.35);
color.b = lerp(color.b, blueAberration, 0.35);
float2 halationOffset = float2(0.0015, 0.0) * (1.0 + smear * 0.35);
float3 halationSource =
sampleVideo(frac(context.uv + halationOffset)).rgb * 0.4 +
sampleVideo(frac(context.uv - halationOffset)).rgb * 0.4 +
sampleVideo(frac(context.uv + halationOffset * 2.0)).rgb * 0.2;
sampleVhsFrame(context.uv + halationOffset).rgb * 0.4 +
sampleVhsFrame(context.uv - halationOffset).rgb * 0.4 +
sampleVhsFrame(context.uv + halationOffset * 2.0).rgb * 0.2;
float halationLuma = dot(halationSource, float3(0.299, 0.587, 0.114));
float halationMask = smoothstep(0.45, 1.0, halationLuma) * halationAmount;
color += halationSource * float3(1.0, 0.38, 0.24) * halationMask * 0.35;