let font
let txt
let glowColor
let size = 30
let glow
let blurFbo
async function setup() {
font = await loadFont('').updatesSize()
txt = createInput('').updatesSize()
glowColor = createColorPicker()
textFont(font)
textSize(size)
createCanvas(
fontWidth(txt.value()) * 1.75,
textLeading() *
txt.value().split('\n').length *
1.75,
WEBGL
)
blurFbo = createFramebuffer()
glow = baseFilterShader().modify(() => {
let c = uniformVec3(() => [
red(glowColor.value())/255,
green(glowColor.value())/255,
blue(glowColor.value())/255,
])
const rnd = (p) => {
let p3 = fract(p.xyx * .1031)
p3 += dot(p3, p3.yzx + 33.33)
return fract((p3.x + p3.y) * p3.z)
}
getColor((inputs, canvasContent) => {
// Slightly vary the distance per
// pixel so the result looks dithered
// and not stepped
const off =
rnd(inputs.texCoord * 123.456)
const toCenter =
-normalize(inputs.texCoord - 0.5)
const glowScale = 0.1
let avg = 0
let total = 0
for (let i = 0; i < 20; i++) {
const sampleScale =
mix(1, (i + off)/20, 0.5)
const sampleCoord =
(inputs.texCoord - 0.5) *
sampleScale + 0.5
const toSample = inputs.texCoord -
sampleCoord
const sampleDist = sqrt(
dot(toSample, toSample)
)
const opacity = getTexture(
canvasContent,
sampleCoord
).a
// Weight the samples higher
// the closer they are to the
// current pixel
const weight =
pow(1 - sampleDist * 2, 8)
total += weight
avg += opacity * weight
}
avg /= total + 1e-6
avg = pow(avg, 0.5) // Boost opacity
return [c, avg]
})
})
}
function draw() {
clear()
fill(255)
textAlign(CENTER, CENTER)
textSize(size)
textFont(font)
text(txt.value(), 0, 0)
filter(glow)
blurFbo.draw(() => {
clear()
text(txt.value(), 0, 0)
filter(BLUR, 1)
})
imageMode(CENTER)
blendMode(ADD)
image(blurFbo, 0, 0)
}