Monorepo for Aesthetic.Computer
aesthetic.computer
Blur Function Implementation Plan#
Overview#
Implementing an efficient Gaussian blur function for the aesthetic-computer graphics library, following the pattern established by existing functions like scroll and suck.
Research Summary: Efficient Gaussian Blur with Linear Sampling#
Key Optimization Techniques#
-
Separable Gaussian Filter
- 2D Gaussian blur can be split into two 1D passes (horizontal + vertical)
- Reduces complexity from O(N²) to O(2N) where N is the filter radius
- For a 9-tap filter: 81 samples → 18 samples (9 horizontal + 9 vertical)
-
Linear Sampling Optimization
- Use GPU's bilinear filtering to sample 2 pixels with 1 texture fetch
- For 9-tap filter: 9 samples → 5 samples per pass
- Total reduction: 81 samples → 10 samples (5 horizontal + 5 vertical)
- ~60% performance improvement over discrete sampling
-
Pascal Triangle Weights
- Use binomial coefficients for Gaussian weights
- Row 6 of Pascal triangle: [1, 6, 15, 20, 15, 6, 1] (sum = 64)
- Normalized weights: [0.015625, 0.09375, 0.234375, 0.3125, 0.234375, 0.09375, 0.015625]
Linear Sampling Mathematics#
For combining two adjacent samples with weights w1 and w2:
- Combined weight:
w_combined = w1 + w2 - Offset from center:
offset = w2 / (w1 + w2)
Example for 9-tap filter with linear sampling:
Offsets: [0.0, 1.3846153846, 3.2307692308]
Weights: [0.2270270270, 0.3162162162, 0.0702702703]
Implementation Strategy#
Function Signature#
function blur(strength = 1, quality = "medium")
Parameters#
strength: Blur radius (1-10+), maps to kernel sizequality: "fast" | "medium" | "high" - affects algorithm choice
Quality Levels#
- Fast: Simple box blur approximation
- Medium: Separable Gaussian with linear sampling (5-tap)
- High: Separable Gaussian with linear sampling (9-tap or larger)
Algorithm Flow#
-
Input Validation
- Check strength bounds (0-10)
- Early return for strength ≤ 0.1
-
Kernel Generation
- Calculate appropriate kernel size based on strength
- Generate Gaussian weights using Pascal triangle or formula
- Optimize for linear sampling (combine adjacent weights)
-
Two-Pass Blur
- Pass 1: Horizontal blur into temporary buffer
- Pass 2: Vertical blur from temp buffer back to main buffer
-
Boundary Handling
- Support for active mask regions
- Proper edge clamping/wrapping
- Respect pan translation
Memory Management#
- Use temporary buffer for intermediate results
- Reuse buffers when possible
- Handle detached buffer edge cases (like other functions)
Performance Considerations#
- Early exit for very small blur amounts
- Accumulator pattern for sub-pixel blur values
- Optional SIMD optimization paths
- Progressive blur for large radii
Code Structure Pattern#
Following the existing pattern from suck and scroll:
// Accumulator for sub-pixel blur values
let blurAccumulator = 0.0;
function blur(strength = 1, quality = "medium") {
if (strength <= 0.1) return; // No blur needed
// Accumulate strength like other effects
blurAccumulator += strength;
const threshold = 0.5;
if (Math.abs(blurAccumulator) < threshold) return;
// Determine working area (mask or full screen)
let minX = 0, minY = 0, maxX = width, maxY = height;
if (activeMask) {
// Apply mask bounds with pan translation
}
// Safety check for detached buffer
if (pixels.buffer && pixels.buffer.detached) {
console.warn('🚨 Pixels buffer detached in blur, recreating');
pixels = new Uint8ClampedArray(width * height * 4);
pixels.fill(0);
}
// Implement separable Gaussian blur with linear sampling
applyHorizontalBlur(/* parameters */);
applyVerticalBlur(/* parameters */);
// Reset accumulator
blurAccumulator = 0.0;
}
Export Pattern#
Add to exports section:
export {
// ... existing exports
blur,
// ... rest of exports
};
Testing Strategy#
- Visual tests with different strength values (1, 2, 5, 10)
- Performance benchmarks vs naive implementation
- Edge case testing (masks, boundaries, zero/negative values)
- Integration with existing effects (scroll, suck, etc.)
Implementation Notes#
- Use separable approach for CPU implementation (no GPU shaders available)
- Implement linear sampling concept using manual interpolation
- Consider progressive blur for very large radii (multiple passes)
- Maintain consistency with existing function patterns and error handling