bevy_psx 0.1.1

A Bevy plugin that provides authentic PlayStation 1 (PSX) style rendering capabilities, including low-resolution rendering, vertex snapping, and palette quantization
Documentation
# Bevy PSX

A Bevy plugin that provides authentic PlayStation 1 (PSX) style rendering capabilities, including low-resolution rendering, vertex snapping, and palette quantization.

## Features

- **Low-Resolution Rendering**: Render your 3D scenes at classic PSX resolutions (320x240, 512x448, etc.)
- **Vertex Snapping**: Authentic PSX-style vertex jittering that recreates the characteristic "wobbly" geometry
- **Optional Palette Quantization**: Apply color palettes to achieve retro color limitations (off by default)
- **Aspect Ratio Matching**: Automatically adjusts resolution to match your window's aspect ratio while maintaining the retro aesthetic
- **Pixelated Upscaling**: Choose between nearest-neighbor (pixelated) or linear filtering for the final output
- **Multiple Palettes**: Load and switch between different color palettes at runtime
- **Automatic Material Conversion**: Seamlessly converts standard Bevy materials to PSX-enhanced materials

## Quick Start

Add the plugin to your Bevy app:

```rust
use bevy::prelude::*;
use bevy_psx::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(PsxCameraPlugin)  // Add the PSX plugin
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands) {
    // Spawn a camera with PSX rendering
    commands.spawn((
        Camera3d::default(),
        Transform::from_xyz(4.0, 2.5, 4.0).looking_at(Vec3::ZERO, Vec3::Y),
        PsxCamera,  // This component enables PSX rendering!
    ));

    // Your 3D objects will automatically get PSX vertex snapping
    // Palette quantization is available but disabled by default
}
```

That's it! Your camera will now render at PSX resolution with automatic vertex snapping applied to all 3D models. Palette quantization is available but disabled by default.

## Configuration

### Render Settings

Control the PSX rendering behavior with `PsxRenderSettings`:

```rust
fn configure_psx(mut settings: ResMut<PsxRenderSettings>) {
    // Set resolution
    settings.render_resolution = UVec2::new(320, 240);  // Classic PSX
    settings.base_resolution = UVec2::new(320, 240);

    // Enable/disable features
    settings.pixelated = true;              // Nearest-neighbor filtering
    settings.aspect_ratio_matching = true;  // Adjust to window aspect ratio
}
```

### Vertex Snapping

Control vertex snapping with `PsxSettings`:

```rust
fn configure_vertex_snapping(mut settings: ResMut<PsxSettings>) {
    settings.snap_enabled = true;
    settings.snap_amount = 64.0;  // Lower = more jittery, Higher = smoother
    
    // Jitter levels guide:
    // 8.0-16.0:   Extreme jitter (very wobbly, experimental)
    // 16.0-32.0:  Maximum jitter (authentic PSX look)
    // 64.0-96.0:  Moderate jitter (recommended for most games)
    // 128.0-256.0: Minimal jitter (smoother movement)
    // 512.0+:     Almost no jitter (modern look with slight retro feel)
}
```

### Understanding Vertex Snapping Jitter

The `snap_amount` value controls how "wobbly" your 3D geometry appears, recreating the characteristic PSX vertex jitter:

- **How it works**: Vertices are snapped to a grid in screen space. Lower values create fewer grid points, causing dramatic jumps between positions as objects move or rotate.

- **Visual impact**:
  - **8.0-32.0**: Very noticeable vertex "popping" - vertices jump visibly between positions
  - **64.0**: Classic PSX feel - noticeable but not overwhelming jitter
  - **128.0+**: Subtle effect - maintains retro feel without being distracting

- **Performance**: All snap amounts have similar performance impact since the calculation is done on the GPU.

- **Recommendation**: Start with **64.0** for an authentic PSX experience, then adjust based on your artistic vision.

### Palette Quantization (Optional)

Color palettes are now handled through the unified shader system with `PsxSettings`:

```rust
fn configure_unified_shader(mut settings: ResMut<PsxSettings>) {
    settings.use_palette = true;      // Turn on palette quantization
    settings.quantize_steps = 32;     // Color reduction steps
}
```

## Controls

The plugin includes built-in keyboard controls (can be seen in the examples):

**Rendering Controls:**
- **1, 2, 3, 4**: Switch between preset resolutions  
- **A**: Toggle aspect ratio matching
- **F**: Toggle pixelated/smooth filtering

**Common Controls (most examples):**
- **V**: Increase vertex snap amount (smoother)
- **B**: Decrease vertex snap amount (more jittery)
- **P**: Toggle palette quantization on/off
- **N**: Switch to next palette
- **M**: Switch to previous palette
- **Q**: Toggle basic quantization on/off
- **E**: Decrease quantization steps (more posterized)
- **R**: Increase quantization steps (smoother gradients)
- **D**: Toggle dithering on/off
- **G**: Switch dither patterns (forward)
- **H**: Switch dither patterns (backward)

**Variable Controls (example-specific):**
- **T**: Toggle vertex snapping (lights example) OR Decrease dither strength (other examples)
- **Y**: Increase dither strength

**⚠️ Important**: Each example may use slightly different key mappings! When you run an example, check the console output for the specific controls available. The most comprehensive controls are in the `lights.rs` example.

## Palettes (Optional Feature)

The plugin automatically loads color palettes but **keeps them off by default**. Each demo can choose whether to turn on palette quantization. Supported formats:

- **Hex files (.hex)**: Each line contains a hex color (with or without #)

Example palette file:
```
# My Custom Palette
000000
ffffff
ff0000
00ff00
0000ff
```

Built-in palettes include:
- Game Boy (4 colors)
- Lospec 2000 (various colors)
- Axulart 32-color palette
- And more!

## Examples

Run any of these examples to see the PSX plugin in action:

### 🎮 Simple PSX Scene
```bash
cargo run --example simple_psx
```
A basic demonstration of PSX rendering with interactive controls for all features.

### 🔄 Rotating Scene with Multiple Objects  
```bash
cargo run --example rotating_scene
```
Multiple animated objects showcasing vertex snapping and palette effects.

### 💡 Advanced Lighting with PSX Camera
```bash
cargo run --example lights
```

**The most comprehensive example** - demonstrates complex lighting scenarios with PSX rendering:

**Features:**
- **Physical Camera System**: Full exposure controls with aperture, shutter speed, and ISO
- **Multiple Light Types**: Point lights, spot lights, directional lights, and ambient lighting  
- **Dynamic Lighting**: Animated directional light and interactive object movement
- **PSX Integration**: See how complex lighting works with vertex snapping and palette quantization
- **Real-time Comparison**: Toggle between full-color and palette-quantized lighting effects

**Controls:**
- `1/2` - Adjust camera aperture (f-stops)
- `3/4` - Adjust shutter speed  
- `5/6` - Adjust ISO sensitivity
- `R` - Reset exposure settings
- `Space` - Toggle ambient light on/off
- `Arrow Keys` - Move objects around the scene
- `Z` - Toggle red point light on/off
- `X` - Toggle green spot light on/off
- `C` - Toggle blue point light on/off
- `G` - Toggle directional light on/off
- `P` - Toggle palette quantization (compare lighting effects!)
- `N/M` - Switch between color palettes
- `V/B` - Adjust vertex snapping intensity
- `T` - Toggle vertex snapping on/off
- `Q/E` - Adjust color quantization steps

### ⚡ Stress Test (Performance Testing)
```bash
cargo run --example object_spawner
```
Extreme performance testing with automatic object spawning up to 1000 objects per frame.

## Technical Details

### Rendering Pipeline

1. Your 3D scene renders to a low-resolution texture
2. Vertex snapping is applied during vertex processing
3. Fragment colors are quantized using the active palette
4. The low-res texture is upscaled to fill your window
5. Filtering (pixelated vs smooth) is applied during upscaling

### Automatic Material Conversion

The plugin automatically converts standard Bevy `StandardMaterial`s to PSX-enhanced materials with:
- Vertex snapping in the vertex shader (always enabled)
- Palette quantization in the fragment shader (when enabled by the demo)
- Maintains all original material properties (textures, colors, etc.)

### Aspect Ratio Matching

When enabled, the plugin automatically adjusts the render resolution based on your window's aspect ratio:

- **Wide windows (16:9, 21:9)**: Keeps height at base resolution, adjusts width
- **Tall windows**: Keeps width at base resolution, adjusts height
- **Square windows**: Uses base resolution as-is

This prevents stretching while maintaining the low-resolution aesthetic.

## Common Resolutions

- **PSX**: 320×240 (4:3)
- **PS2**: 512×448 (8:7, close to 4:3)
- **SNES**: 256×224 (8:7)
- **Custom**: Any resolution you want!

## Performance

The PSX rendering adds minimal overhead:
- Low-resolution rendering actually improves performance
- Vertex snapping is GPU-accelerated
- Automatic material conversion happens once per material

## License

This project is licensed under the MIT License - see the LICENSE file for details.

## Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.

## Compatibility

- **Bevy Version**: 0.17.1
- **Platforms**: All platforms supported by Bevy
- **Rendering**: Compatible with Bevy's PBR pipeline

## Acknowledgments

Inspired by the distinctive visual style of original PlayStation games and the technical limitations that created their unique aesthetic.