Skip to content

agusegui/dithervid

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

Video Dithering Shader

This demo applies the Paper Shaders ImageDithering effect to a live video using WebGL2.

Usage

Run a local server:

npx serve .
# or
python3 -m http.server 8000

Open http://localhost:3000 (or the port shown).

Why Direct WebGL?

The ShaderMount class from @paper-design/shaders only supports HTMLImageElement or string URLs as texture sources. It doesn't handle HTMLVideoElement natively. To use video, we must use WebGL2 directly and manage the texture ourselves.

How Video Textures Work

WebGL can sample directly from an HTMLVideoElement. The key is calling gl.texImage2D() with the video element every frame to upload the current video frame to the GPU:

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video);

This is a CPU→GPU transfer, but browsers heavily optimize this path for video.

Uniform Types

The imageDitheringFragmentShader expects specific types:

Uniform Type Notes
u_resolution vec2 Canvas width/height
u_pixelRatio float window.devicePixelRatio
u_originX, u_originY float Origin point (0.5 = center)
u_worldWidth, u_worldHeight float World dimensions
u_fit float 1 = contain, 2 = cover
u_scale float Scale factor
u_rotation float Rotation in radians
u_offsetX, u_offsetY float Position offset
u_image sampler2D Set via uniform1i with texture unit
u_imageAspectRatio float Video width / height
u_colorFront vec4 Primary dither color (RGBA 0-1)
u_colorBack vec4 Background color (RGBA 0-1)
u_colorHighlight vec4 Highlight color (RGBA 0-1)
u_type float 1=random, 2=2x2, 3=4x4, 4=8x8
u_pxSize float Dither pixel size
u_colorSteps float Number of color steps
u_originalColors bool Use original image colors
u_inverted bool Invert the effect

Mobile Performance

This approach is reasonably efficient. Main costs:

  1. texImage2D per frame - Unavoidable for video, but well-optimized by browsers
  2. Fragment shader - Runs per-pixel

Optimizations for Mobile

  • Lower canvas resolution - e.g., 320×180 instead of 640×360
  • Increase u_pxSize - Larger dither pixels = fewer calculations
  • Use requestVideoFrameCallback() - Only render when video has a new frame
  • Skip frames - Render every 2nd or 3rd frame if needed

Files

├── index.html    # Entry point
├── main.js       # WebGL setup and render loop
├── styles.css    # Styling
└── README.md     # This file

About

Video dithering shader demo using Paper Shaders

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors