McRogueFace/RENDERTEXTURE_DESIGN.md

4.9 KiB

RenderTexture Overhaul Design Document

Overview

This document outlines the design for implementing RenderTexture support across all UIDrawable classes in McRogueFace. This is Issue #6 and represents a major architectural change to the rendering system.

Goals

  1. Automatic Clipping: Children rendered outside parent bounds should be clipped
  2. Off-screen Rendering: Enable post-processing effects and complex compositing
  3. Performance: Cache static content, only re-render when changed
  4. Backward Compatibility: Existing code should continue to work

Current State

Classes Already Using RenderTexture:

  • UIGrid: Uses a 1920x1080 RenderTexture for compositing grid view
  • SceneTransition: Uses two 1024x768 RenderTextures for transitions
  • HeadlessRenderer: Uses RenderTexture for headless mode

Classes Using Direct Rendering:

  • UIFrame: Renders box and children directly
  • UICaption: Renders text directly
  • UISprite: Renders sprite directly

Design Decisions

1. Opt-in Architecture

Not all UIDrawables need RenderTextures. We'll use an opt-in approach:

class UIDrawable {
protected:
    // RenderTexture support (opt-in)
    std::unique_ptr<sf::RenderTexture> render_texture;
    sf::Sprite render_sprite;
    bool use_render_texture = false;
    bool render_dirty = true;
    
    // Enable RenderTexture for this drawable
    void enableRenderTexture(unsigned int width, unsigned int height);
    void updateRenderTexture();
};

2. When to Use RenderTexture

RenderTextures will be enabled for:

  1. UIFrame with clipping enabled (new property: clip_children = true)
  2. UIDrawables with effects (future: shaders, blend modes)
  3. Complex composites (many children that rarely change)

3. Render Flow

Standard Flow:
render() → render directly to target

RenderTexture Flow:
render() → if dirty → clear RT → render to RT → dirty = false
         → draw RT sprite to target

4. Dirty Flag Management

Mark as dirty when:

  • Properties change (position, size, color, etc.)
  • Children added/removed
  • Child marked as dirty (propagate up)
  • Animation frame

5. Size Management

RenderTexture size options:

  1. Fixed Size: Set at creation (current UIGrid approach)
  2. Dynamic Size: Match bounds, recreate on resize
  3. Pooled Sizes: Use standard sizes from pool

We'll use Dynamic Size with lazy creation.

Implementation Plan

Phase 1: Base Infrastructure (This PR)

  1. Add RenderTexture members to UIDrawable
  2. Add enableRenderTexture() method
  3. Implement dirty flag system
  4. Add clip_children property to UIFrame

Phase 2: UIFrame Implementation

  1. Update UIFrame::render() to use RenderTexture when clipping
  2. Test with nested frames
  3. Verify clipping works correctly

Phase 3: Performance Optimization

  1. Implement texture pooling
  2. Add dirty flag propagation
  3. Profile and optimize

Phase 4: Extended Features

  1. Blur/glow effects using RenderTexture
  2. Viewport-based rendering (#8)
  3. Screenshot improvements

API Changes

Python API:

# Enable clipping on frames
frame.clip_children = True  # New property

# Future: effects
frame.blur_amount = 5.0
sprite.glow_color = Color(255, 200, 100)

C++ API:

// Enable RenderTexture
frame->enableRenderTexture(width, height);
frame->setClipChildren(true);

// Mark dirty
frame->markDirty();

Performance Considerations

  1. Memory: Each RenderTexture uses GPU memory (width * height * 4 bytes)
  2. Creation Cost: Creating RenderTextures is expensive, use pooling
  3. Clear Cost: Clearing large RenderTextures each frame is costly
  4. Bandwidth: Drawing to RenderTexture then to screen doubles bandwidth

Migration Strategy

  1. All existing code continues to work (direct rendering by default)
  2. Gradually enable RenderTexture for specific use cases
  3. Profile before/after to ensure performance gains
  4. Document best practices

Risks and Mitigation

Risk Mitigation
Performance regression Opt-in design, profile extensively
Memory usage increase Texture pooling, size limits
Complexity increase Clear documentation, examples
Integration issues Extensive testing with SceneTransition

Success Criteria

  1. ✓ Frames can clip children to bounds
  2. ✓ No performance regression for direct rendering
  3. ✓ Scene transitions continue to work
  4. ✓ Memory usage is reasonable
  5. ✓ API is intuitive and documented

Future Extensions

  1. Shader Support (#106): RenderTextures enable post-processing shaders
  2. Particle Systems (#107): Render particles to texture for effects
  3. Caching: Static UI elements cached in RenderTextures
  4. Resolution Independence: RenderTextures for DPI scaling

Conclusion

This design provides a foundation for professional rendering capabilities while maintaining backward compatibility and performance. The opt-in approach allows gradual adoption and testing.