Industry
  • Visual Interaction
Technologies
  • r3f
  • shader

Ascii Video Player

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/>