4.9 KiB
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
- Automatic Clipping: Children rendered outside parent bounds should be clipped
- Off-screen Rendering: Enable post-processing effects and complex compositing
- Performance: Cache static content, only re-render when changed
- 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:
- UIFrame with clipping enabled (new property:
clip_children = true
) - UIDrawables with effects (future: shaders, blend modes)
- 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:
- Fixed Size: Set at creation (current UIGrid approach)
- Dynamic Size: Match bounds, recreate on resize
- Pooled Sizes: Use standard sizes from pool
We'll use Dynamic Size with lazy creation.
Implementation Plan
Phase 1: Base Infrastructure (This PR)
- Add RenderTexture members to UIDrawable
- Add
enableRenderTexture()
method - Implement dirty flag system
- Add
clip_children
property to UIFrame
Phase 2: UIFrame Implementation
- Update UIFrame::render() to use RenderTexture when clipping
- Test with nested frames
- Verify clipping works correctly
Phase 3: Performance Optimization
- Implement texture pooling
- Add dirty flag propagation
- Profile and optimize
Phase 4: Extended Features
- Blur/glow effects using RenderTexture
- Viewport-based rendering (#8)
- 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
- Memory: Each RenderTexture uses GPU memory (width * height * 4 bytes)
- Creation Cost: Creating RenderTextures is expensive, use pooling
- Clear Cost: Clearing large RenderTextures each frame is costly
- Bandwidth: Drawing to RenderTexture then to screen doubles bandwidth
Migration Strategy
- All existing code continues to work (direct rendering by default)
- Gradually enable RenderTexture for specific use cases
- Profile before/after to ensure performance gains
- 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
- ✓ Frames can clip children to bounds
- ✓ No performance regression for direct rendering
- ✓ Scene transitions continue to work
- ✓ Memory usage is reasonable
- ✓ API is intuitive and documented
Future Extensions
- Shader Support (#106): RenderTextures enable post-processing shaders
- Particle Systems (#107): Render particles to texture for effects
- Caching: Static UI elements cached in RenderTextures
- 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.