208 lines
6.7 KiB
Markdown
208 lines
6.7 KiB
Markdown
# HCIE Brush Engine
|
||
|
||
High-performance procedural brush engine for paint/drawing applications. Provides 33 brush styles with GPU-accelerated test tool.
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
hcie-brush-engine/
|
||
├── Cargo.toml # Project manifest
|
||
├── src/
|
||
│ ├── lib.rs # Core library: brush stamps, strokes, FFI
|
||
│ ├── dynamics.rs # Pressure, velocity, tilt mapping
|
||
│ └── presets.rs # Predefined brush presets (28 presets)
|
||
├── examples/
|
||
│ └── brush_test.rs # GPU-accelerated tiled test tool (egui/eframe)
|
||
└── tests/
|
||
└── stamp.rs # Integration tests
|
||
```
|
||
|
||
## Quick Start
|
||
|
||
### Run Tests
|
||
```bash
|
||
cargo test
|
||
```
|
||
|
||
### Run Test GUI (Brush Visualizer)
|
||
```bash
|
||
cargo run --example brush_test
|
||
```
|
||
|
||
The test tool opens a window with:
|
||
- **Canvas**: 512–4096px resolution, auto-scaled to window
|
||
- **Tiled GPU rendering**: 512px tiles, only modified tiles uploaded
|
||
- **Brush presets**: 28 preset brushes in categories (Basic, Sketch, Paint, Nature, Texture, Effect, Mixer)
|
||
- **Parameters**: Size, hardness, opacity, spacing sliders
|
||
- **FPS cap**: 30 / 60 / 165 / Unlimited selectable
|
||
- **Live diagnostics**: FPS counter, dirty tile count, stroke counter
|
||
|
||
### Run Benchmarks
|
||
```bash
|
||
cargo test --release
|
||
```
|
||
|
||
---
|
||
|
||
## Library API
|
||
|
||
### Core Types
|
||
|
||
```rust
|
||
// Brush style enum (33 variants)
|
||
pub enum BrushStyle { Round, Square, HardRound, SoftRound, Star, Noise, Texture,
|
||
Spray, Pencil, Pen, Calligraphy, Oil, Charcoal, Leaf, Rock, Meadow, Wood,
|
||
Watercolor, Marker, Sketch, Hatch, Glow, Airbrush, Crayon, WetPaint, InkPen,
|
||
Clouds, Dirt, Tree, Bristle, Mixer, Blender, Bitmap }
|
||
|
||
// Brush tip configuration
|
||
pub struct BrushTip {
|
||
pub style: BrushStyle,
|
||
pub size: f32, // diameter in pixels
|
||
pub opacity: f32, // 0.0–1.0
|
||
pub hardness: f32, // 0.0 (soft) – 1.0 (hard)
|
||
pub spacing: f32, // 0.01–5.0, relative to size
|
||
pub jitter_amount: f32, // random position jitter
|
||
pub scatter_amount: f32, // random scatter offset
|
||
pub angle: f32, // brush angle in radians
|
||
pub roundness: f32, // 0.0–1.0, 1.0 = perfect circle
|
||
pub spray_particle_size: f32,
|
||
pub spray_density: u32,
|
||
pub bitmap_pixels: Vec<u8>, // for Bitmap brush style
|
||
pub bitmap_w: u32,
|
||
pub bitmap_h: u32,
|
||
}
|
||
```
|
||
|
||
### Essential Functions
|
||
|
||
| Function | Description |
|
||
|----------|-------------|
|
||
| `generate_brush_stamp(tip: &BrushTip) -> Vec<u8>` | Procedural alpha mask (diameter × diameter, 0-255) |
|
||
| `sample_stamp(stamp: &[u8], diameter: usize, x: f32, y: f32) -> f32` | Bilinear sample from stamp |
|
||
| `brush_spacing_pixels(size: f32, spacing_ratio: f32) -> f32` | Effective spacing in pixels |
|
||
| `jitter_offset(jitter_amount: f32, size: f32) -> (f32, f32)` | Random jitter offset |
|
||
| `scatter_offset(scatter_amount: f32, size: f32) -> (f32, f32)` | Random scatter offset |
|
||
| `draw_dab(pixels: &mut [u8], w: u32, h: u32, cx: f32, cy: f32, size: f32, hardness: f32, color: [u8;4], opacity: f32, is_eraser: bool, mask: Option<&[u8]>)` | Single brush dab (RGBA) |
|
||
| `draw_specialized_stroke(...)` | Full stroke with interpolation for all brush styles |
|
||
|
||
### Brush Drawing Functions
|
||
|
||
Each brush style has its own signature (oil, charcoal, watercolor, calligraphy, marker, glow, airbrush, spray, pencil, square, wetpaint, mixer, leaf, crayon, tree, meadow, rock, clouds, dirt, stipple, bristle, wood, sketch, hatch).
|
||
|
||
See `src/lib.rs` for full signatures.
|
||
|
||
### Presets (`hcie_brush_engine::presets`)
|
||
|
||
```rust
|
||
pub struct BrushPreset {
|
||
pub id: String,
|
||
pub name: String,
|
||
pub category: String,
|
||
pub tip: BrushTip,
|
||
pub style: BrushStyle,
|
||
pub pressure_size: bool,
|
||
pub pressure_opacity: bool,
|
||
pub pressure_flow: bool,
|
||
pub jitter_position: f32,
|
||
pub jitter_angle: f32,
|
||
}
|
||
|
||
impl BrushPreset {
|
||
pub fn all_defaults() -> Vec<Self>; // returns all 28 presets
|
||
pub fn basic_round() -> Self;
|
||
pub fn hard_round() -> Self;
|
||
pub fn soft_round() -> Self;
|
||
pub fn soft_airbrush() -> Self;
|
||
pub fn pencil() -> Self;
|
||
pub fn ink_pen() -> Self;
|
||
pub fn charcoal() -> Self;
|
||
pub fn marker() -> Self;
|
||
pub fn watercolor_wash() -> Self;
|
||
pub fn watercolor() -> Self;
|
||
pub fn oil_paint() -> Self;
|
||
pub fn gouache() -> Self;
|
||
pub fn crayon() -> Self;
|
||
pub fn spray() -> Self;
|
||
pub fn calligraphy() -> Self;
|
||
pub fn smudge() -> Self;
|
||
pub fn mixer() -> Self;
|
||
pub fn blender() -> Self;
|
||
pub fn meadow_grass() -> Self;
|
||
pub fn rock_texture() -> Self;
|
||
pub fn clouds() -> Self;
|
||
pub fn dirt() -> Self;
|
||
pub fn tree_bark() -> Self;
|
||
pub fn stipple() -> Self;
|
||
pub fn splatter() -> Self;
|
||
pub fn pastel() -> Self;
|
||
pub fn bristle() -> Self;
|
||
pub fn glow() -> Self;
|
||
pub fn hatch() -> Self;
|
||
pub fn sketch() -> Self;
|
||
}
|
||
```
|
||
|
||
### Dynamics (`hcie_brush_engine::dynamics`)
|
||
|
||
```rust
|
||
pub struct StrokeDynamics {
|
||
pub pressure: f32, // 0.0–1.0
|
||
pub velocity: f32, // px/frame
|
||
pub tilt: (f32, f32), // degrees
|
||
}
|
||
|
||
pub fn effective_size(base: f32, dyn: &StrokeDynamics, sensitive: bool) -> f32;
|
||
pub fn effective_opacity(base: f32, dyn: &StrokeDynamics, sensitive: bool) -> f32;
|
||
pub fn effective_flow(base: f32, dyn: &StrokeDynamics, sensitive: bool) -> f32;
|
||
pub fn velocity_size_modifier(velocity: f32) -> f32;
|
||
pub fn build_dynamic_tip(base: &BrushTip, dyn: &StrokeDynamics, press_size: bool, press_opacity: bool) -> BrushTip;
|
||
pub fn simulate_pressure_from_velocity(velocity: f32, max_velocity: f32) -> f32;
|
||
pub struct VelocityTracker { /* tracks velocity from consecutive points */ }
|
||
```
|
||
|
||
### FFI (C Foreign Function Interface)
|
||
|
||
The library builds as `cdylib`. Primary entry point:
|
||
|
||
```c
|
||
// See src/lib.rs for exact signatures
|
||
void draw_specialized_stroke_ffi(
|
||
uint8_t* pixels, uint32_t pixels_len,
|
||
uint32_t width, uint32_t height,
|
||
const float* points, uint32_t points_count,
|
||
int32_t brush_style,
|
||
float size, float hardness,
|
||
const uint8_t* color,
|
||
float opacity, float spacing_ratio,
|
||
uint8_t is_eraser,
|
||
/* ... mask/stroke_mask/bg params ... */
|
||
);
|
||
```
|
||
|
||
For detailed FFI signatures, see the `#[no_mangle]` functions at the bottom of `src/lib.rs`.
|
||
|
||
---
|
||
|
||
## Linking Without Source Code
|
||
|
||
### Cargo (Rust Projects)
|
||
```toml
|
||
[dependencies]
|
||
hcie-brush-engine = { git = "https://github.com/your-org/hcie-brush-engine" }
|
||
# or local path:
|
||
hcie-brush-engine = { path = "../hcie-brush-engine" }
|
||
```
|
||
|
||
### C/C++ Projects
|
||
1. Build the library:
|
||
```bash
|
||
cargo build --release
|
||
```
|
||
2. Link against the produced shared library (`target/release/libhcie_brush_engine.so` / `.dylib` / `.dll`).
|
||
3. Include the header generated by `cbindgen` or use the raw C declarations from the `#[no_mangle]` functions in `src/lib.rs`.
|
||
|
||
## License
|
||
|
||
[Your license here]
|