Root cause: Chromium limits ~16 simultaneous WebGL contexts. When scrolling
through a feed of 20+ shader cards, older contexts get silently evicted.
Once a context is lost on a canvas element, getContext('webgl2') returns null
on that same element forever — even after loseContext()/restore cycles.
Solution: The ShaderCanvas component now renders a container div and creates
canvas elements imperatively. When re-entering viewport:
1. Check if existing GL context is still alive (isContextLost)
2. If alive: just restart the animation loop
3. If dead: remove the old canvas, create a fresh DOM element, get a new
context, recompile, and start rendering
This means scrolling down creates new contexts and scrolling back up
replaces dead canvases with fresh ones. At any given time only ~9 visible
canvases hold active contexts — well within Chrome's limit.
Also: 200px rootMargin on IntersectionObserver pre-compiles shaders
before cards enter viewport for smoother scroll experience.
|
||
|---|---|---|
| .. | ||
| api | ||
| frontend | ||
| mcp | ||
| nginx/conf | ||
| renderer | ||