mirror of
https://github.com/YACReader/yacreader
synced 2026-03-01 10:22:58 -05:00
288 lines
7.8 KiB
Markdown
288 lines
7.8 KiB
Markdown
# YACReader Flow RHI Implementation
|
|
|
|
This directory contains the QRhiWidget-based implementation of the YACReader 3D cover flow, providing cross-platform 3D rendering support for Qt 6.7+.
|
|
|
|
## Overview
|
|
|
|
The RHI (Rendering Hardware Interface) implementation is a modern replacement for the OpenGL-based flow (`yacreader_flow_gl`) that:
|
|
|
|
- ✅ Supports **multiple graphics APIs**: Vulkan, Metal, Direct3D 11/12, OpenGL
|
|
- ✅ Provides **native performance** on modern platforms (Metal on macOS, D3D on Windows)
|
|
- ✅ Maintains **100% API compatibility** with the OpenGL version
|
|
- ✅ Works seamlessly with **Qt 6.7+** while Qt5 continues using OpenGL
|
|
- ✅ Enables **future-proof** rendering infrastructure
|
|
|
|
## Architecture
|
|
|
|
### Class Hierarchy
|
|
|
|
```
|
|
QRhiWidget (Qt base class)
|
|
└── YACReaderFlow3D (Base implementation)
|
|
├── YACReaderComicFlow3D (File path-based loading for library)
|
|
└── YACReaderPageFlow3D (Byte array-based loading for viewer)
|
|
```
|
|
|
|
### Files
|
|
|
|
- **yacreader_flow_rhi.h** - Header with class definitions
|
|
- **yacreader_flow_rhi.cpp** - Implementation
|
|
- **shaders/** - GLSL 450 shaders and compiled .qsb files
|
|
- **README.md** - This file
|
|
|
|
## Key Features
|
|
|
|
### Graphics Pipeline
|
|
|
|
The implementation uses:
|
|
- **Instanced rendering** for efficient batch drawing
|
|
- **Dual-pass rendering** (reflections + covers)
|
|
- **MSAA** (4x by default) for anti-aliasing
|
|
- **Depth testing** and back-face culling
|
|
- **Alpha blending** for transparency
|
|
|
|
### Resource Management
|
|
|
|
QRhi resources managed:
|
|
- `QRhiBuffer` for vertices, instance data, and uniforms
|
|
- `QRhiTexture` for cover images, marks, and default texture
|
|
- `QRhiSampler` for texture filtering
|
|
- `QRhiGraphicsPipeline` for render state
|
|
- `QRhiShaderResourceBindings` for uniform/texture bindings
|
|
|
|
### Shader System
|
|
|
|
Shaders are written in **GLSL 4.50** and compiled to `.qsb` format supporting:
|
|
- OpenGL ES 2.0, 3.0
|
|
- OpenGL 2.1, 3.0+
|
|
- HLSL (Direct3D 11/12)
|
|
- Metal Shading Language (macOS/iOS)
|
|
|
|
## Integration
|
|
|
|
### Qt5 vs Qt6 Selection
|
|
|
|
The build system automatically selects the appropriate implementation:
|
|
|
|
**Qt 5.x**: Uses `YACReaderFlowGL` (OpenGL-based)
|
|
**Qt 6.0-6.6**: Uses `YACReaderFlowGL` (OpenGL-based)
|
|
**Qt 6.7+**: Uses `YACReaderFlow3D` (RHI-based) if `YACREADER_USE_RHI` is defined
|
|
|
|
### Type Aliases
|
|
|
|
Applications use type aliases for seamless switching:
|
|
|
|
```cpp
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) && defined(YACREADER_USE_RHI)
|
|
using YACReaderPageFlowImpl = YACReaderPageFlow3D;
|
|
using YACReaderComicFlowImpl = YACReaderComicFlow3D;
|
|
#else
|
|
using YACReaderPageFlowImpl = YACReaderPageFlowGL;
|
|
using YACReaderComicFlowImpl = YACReaderComicFlowGL;
|
|
#endif
|
|
```
|
|
|
|
### Example Usage (YACReader Viewer)
|
|
|
|
```cpp
|
|
// goto_flow_gl.cpp
|
|
flow = new YACReaderPageFlowImpl(this);
|
|
flow->setShowMarks(false);
|
|
flow->populate(numPages);
|
|
connect(flow, &YACReaderPageFlowImpl::selected, this, &GoToFlowGL::goToPage);
|
|
```
|
|
|
|
### Example Usage (YACReaderLibrary)
|
|
|
|
```cpp
|
|
// comic_flow_widget.cpp
|
|
flow = new YACReaderComicFlowImpl(parent);
|
|
flow->setImagePaths(pathsList);
|
|
connect(flow, &YACReaderComicFlowImpl::centerIndexChanged,
|
|
this, &ComicFlowWidget::centerIndexChanged);
|
|
```
|
|
|
|
## API Compatibility
|
|
|
|
All public methods from `YACReaderFlowGL` are preserved:
|
|
|
|
### Navigation
|
|
- `showPrevious()`, `showNext()`
|
|
- `setCurrentIndex(int)`, `setCenterIndex(unsigned int)`
|
|
- `showSlide(int)`, `centerIndex()`
|
|
|
|
### Configuration
|
|
- `setPreset(const Preset &)`
|
|
- `setPerformance(Performance)`
|
|
- `setFlowRightToLeft(bool)`
|
|
- `setZoom(int)`, `setRotation(int)`
|
|
- `setCF_RX/RY/RZ(int)`, `setCF_Y/Z(int)`
|
|
- `setX_Distance(int)`, `setCenter_Distance(int)`, etc.
|
|
|
|
### Appearance
|
|
- `setBackgroundColor(const QColor &)`
|
|
- `setTextColor(const QColor &)`
|
|
- `setShadingColor(const QColor &)`
|
|
- `setShowMarks(bool)`, `setMarks(QVector<...>)`
|
|
|
|
### Content Management
|
|
- `populate(int)`, `clear()`, `reset()`, `reload()`
|
|
- `insert()`, `remove(int)`, `add(int)`, `replace()`
|
|
- Subclass-specific: `setImagePaths()`, `resortCovers()`, etc.
|
|
|
|
## Building
|
|
|
|
### Prerequisites
|
|
|
|
1. **Qt 6.7 or later**
|
|
2. **qsb tool** (Qt Shader Baker) in PATH
|
|
3. **C++17 compiler**
|
|
|
|
### Compile Shaders
|
|
|
|
Before building YACReader, compile the shaders:
|
|
|
|
```bash
|
|
cd common/rhi/shaders
|
|
# Windows
|
|
compile_shaders.bat
|
|
|
|
# Unix/macOS
|
|
chmod +x compile_shaders.sh
|
|
./compile_shaders.sh
|
|
```
|
|
|
|
This generates `flow.vert.qsb` and `flow.frag.qsb` which are embedded via `shaders.qrc`.
|
|
|
|
### Build YACReader
|
|
|
|
The `.pro` files automatically include RHI sources for Qt 6.7+:
|
|
|
|
```bash
|
|
qmake YACReader.pro
|
|
make
|
|
```
|
|
|
|
For Qt 5 builds, the OpenGL version is used automatically.
|
|
|
|
## Graphics API Selection
|
|
|
|
QRhiWidget auto-selects the best API per platform:
|
|
|
|
- **macOS/iOS**: Metal (native)
|
|
- **Windows**: Direct3D 11 (default) or Direct3D 12
|
|
- **Linux**: Vulkan or OpenGL
|
|
- **Android**: OpenGL ES 3.0 or Vulkan
|
|
|
|
You can force a specific API via environment variables (for testing):
|
|
|
|
```bash
|
|
# Force OpenGL
|
|
export QSG_RHI_BACKEND=opengl
|
|
|
|
# Force Vulkan
|
|
export QSG_RHI_BACKEND=vulkan
|
|
|
|
# Force Direct3D 11 (Windows)
|
|
set QSG_RHI_BACKEND=d3d11
|
|
```
|
|
|
|
## Performance
|
|
|
|
Performance tiers match the OpenGL version:
|
|
|
|
- **Low**: 8 covers loaded, 128px textures (page flow) / 200px (comic flow)
|
|
- **Medium**: 10 covers, 196px / 256px textures
|
|
- **High**: 12 covers, 256px / 320px textures
|
|
- **Ultra High**: 14-16 covers, full resolution textures
|
|
|
|
Texture loading happens asynchronously via worker threads (`ImageLoader3D`, `ImageLoaderByteArray3D`).
|
|
|
|
## Debugging
|
|
|
|
### Enable Validation Layers
|
|
|
|
For debugging graphics issues, enable validation:
|
|
|
|
```cpp
|
|
flow->setDebugLayerEnabled(true); // Call before widget is shown
|
|
```
|
|
|
|
This activates:
|
|
- **Vulkan**: VK_LAYER_KHRONOS_validation
|
|
- **Direct3D**: D3D11 debug layer
|
|
- **Metal**: Metal API validation
|
|
|
|
### Check Active Graphics API
|
|
|
|
```cpp
|
|
QRhi *rhi = flow->rhi();
|
|
qDebug() << "Backend:" << rhi->backend();
|
|
qDebug() << "Driver:" << rhi->driverInfo();
|
|
```
|
|
|
|
### Common Issues
|
|
|
|
**Problem**: Shaders fail to load
|
|
**Solution**: Ensure `.qsb` files are compiled and included in resources
|
|
|
|
**Problem**: Black screen on Qt 6.7
|
|
**Solution**: Check if `YACREADER_USE_RHI` is defined in build
|
|
|
|
**Problem**: Crashes on resize/reparent
|
|
**Solution**: `releaseResources()` properly cleans up all QRhi objects
|
|
|
|
## Migration from OpenGL
|
|
|
|
The RHI version is a **drop-in replacement** requiring no application code changes beyond the build system.
|
|
|
|
### What's Different (Internal)
|
|
|
|
| OpenGL API | QRhi Equivalent |
|
|
|------------|-----------------|
|
|
| `glDrawArraysInstanced()` | `cb->drawIndexed(instanceCount)` |
|
|
| `glUniform*()` | Update `QRhiBuffer` with uniform data |
|
|
| `glBindTexture()` | `QRhiShaderResourceBindings` |
|
|
| `glBlendFunc()` | `QRhiGraphicsPipeline::setTargetBlends()` |
|
|
| `glEnable(GL_DEPTH_TEST)` | `pipeline->setDepthTest(true)` |
|
|
|
|
### What's the Same
|
|
|
|
- All public API methods and signatures
|
|
- Animation system and timing
|
|
- Preset configurations
|
|
- Event handling (mouse, keyboard, wheel)
|
|
- Worker thread texture loading
|
|
- Performance tiers
|
|
|
|
## Known Limitations
|
|
|
|
1. **Qt Version**: Requires Qt 6.7+ (released April 2024)
|
|
2. **QRhi Stability**: QRhi APIs may change in minor Qt releases
|
|
3. **Mixed Renderers**: Only one graphics API per window
|
|
4. **Shader Compilation**: Must recompile shaders when modifying source
|
|
|
|
## Future Improvements
|
|
|
|
Potential enhancements:
|
|
- [ ] GPU-side frustum culling
|
|
- [ ] Compute shader for texture generation
|
|
- [ ] HDR/wide color gamut support
|
|
- [ ] Ray-traced reflections (via RHI compute)
|
|
- [ ] Dynamic LOD based on distance
|
|
|
|
## References
|
|
|
|
- [QRhiWidget Class Documentation](https://doc.qt.io/qt-6/qrhiwidget.html)
|
|
- [QRhi Overview](https://doc.qt.io/qt-6/qrhi.html)
|
|
- [Qt RHI Examples](https://doc.qt.io/qt-6/qtwidgets-rhi-cuberhiwidget-example.html)
|
|
- [Qt Shader Tools (qsb)](https://doc.qt.io/qt-6/qtshadertools-index.html)
|
|
|
|
## License
|
|
|
|
Same as YACReader project license.
|
|
|
|
## Author
|
|
|
|
Generated as part of the YACReader OpenGL modernization initiative.
|