A video player implemented using shaders
There are two approaches to ASCII-style image processing: brightness mapping and structure-based methods. I’ve chosen the former for its simplicity and efficiency, making it well-suited for real-time video processing in the browser. While it may not achieve the same level of refinement as structure-based techniques, it remains effective in practice. For those interested in the structure-based approach, see the research paper Structure-based ASCII Art.
Preprocess character textures
export const CHARSETS = {
default: " .:-=+*#@",
simple: " .:*#",
detailed:
" .'`^\",:;Il!i><~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$",
};
Luminance calculation
float brightness = 0.3 \ R + 0.59 \ G + 0.11 \ B
Map the luminance value to the coordinates of the character texture.
float charIndex = floor(brightness * (asciiAtlasSize.x - 1.0) + 0.5);
vec2 asciiUv = vec2(
(charIndex + cellUv.x) / asciiAtlasSize.x,
cellUv.y
);
vec4 asciiChar = texture2D(tAsciiAtlas, asciiUv);
Render video texture
<a.mesh
sizeScale
color
lighting
brightness
font
effect
...
>
{...primitive, material}
<a.mesh/>