Summary
Render parallax background layers (ImageLayer) as a single screen-aligned quad with UV offset computed in the shader, instead of tiling multiple drawImage calls. The shader handles wrapping, scrolling, and parallax ratio — no CPU-side tile loop needed.
Current State
- `ImageLayer` in `src/renderable/imagelayer.js` draws the background image by tiling it across the viewport
- For repeating backgrounds, it calculates how many copies are needed and calls `drawImage()` for each
- The parallax ratio adjusts the scroll speed, but the CPU still iterates and pushes vertices per tile
Proposed Approach
A fragment shader that:
- Takes the background texture, scroll offset, and parallax ratio as uniforms
- Computes wrapped UVs per pixel for seamless tiling
- Renders the entire layer as one quad — one draw call regardless of viewport size or repeat count
uniform sampler2D uBackground;
uniform vec2 uScrollOffset; // camera position * parallax ratio
uniform vec2 uTextureSize; // background image size
uniform vec2 uViewportSize; // camera viewport size
vec4 apply(vec4 color, vec2 uv) {
vec2 pixelPos = uv * uViewportSize + uScrollOffset;
vec2 wrappedUV = fract(pixelPos / uTextureSize);
return texture2D(uBackground, wrappedUV);
}
Benefits
- Single draw call per background layer (currently N draw calls for N visible tiles)
- Smooth sub-pixel scrolling with no seams (GPU handles texture wrapping)
- Trivially supports both horizontal and vertical repeat
- Could extend to support scaling, rotation, or distortion effects in the shader
Considerations
- Canvas fallback: keep existing tile-by-tile rendering for Canvas mode
- Non-repeating backgrounds: shader can clamp UVs instead of wrapping
- Multiple background layers: each is still a separate quad (one draw call each)
- Integration: could be opt-in via `ImageLayer.gpuRendering = true` or automatic when WebGL is active
References
- `ImageLayer`: `src/renderable/imagelayer.js`
- `ShaderEffect`: `src/video/webgl/shadereffect.js`
Summary
Render parallax background layers (ImageLayer) as a single screen-aligned quad with UV offset computed in the shader, instead of tiling multiple drawImage calls. The shader handles wrapping, scrolling, and parallax ratio — no CPU-side tile loop needed.
Current State
Proposed Approach
A fragment shader that:
Benefits
Considerations
References