# How to Fine-Tune HDR and Bloom Rendering Post-Processing Effects in Pyrite64 for Optimal Visual Quality

> Master HDR and Bloom in Pyrite64. Learn to fine-tune hdrFactor, blurSteps, and bloomThreshold via Config struct for stunning post-processing visual quality. Optimize graphics now.

- Repository: [Max Bebök/pyrite64](https://github.com/hailtododongo/pyrite64)
- Tags: how-to-guide
- Published: 2026-02-19

---

**Fine-tune HDR and Bloom in Pyrite64 by adjusting the `Config` struct parameters—`hdrFactor` for exposure, `blurSteps` for glow smoothness, and `bloomThreshold` for highlight selectivity—then apply them via `postProc[frameIdx].setConf()` before each frame.**

Pyrite64 implements a hardware-accelerated HDR-Bloom pipeline specifically designed for Nintendo 64-style rendering. The engine exposes fine-grained control over post-processing through a centralized configuration system defined in [`n64/engine/include/renderer/hdr/postProcess.h`](https://github.com/HailToDodongo/pyrite64/blob/main/n64/engine/include/renderer/hdr/postProcess.h) and consumed during the frame rendering loop in [`pipelineHDRBloom.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/pipelineHDRBloom.cpp). Understanding these parameters allows you to balance cinematic visual fidelity against the limited computational budget of N64-class hardware.

## Understanding the HDR-Bloom Configuration Structure

The `P64::Renderer::HDR::Config` struct serves as the single source of truth for all post-processing parameters. You instantiate this struct, populate its fields, and pass it to the pipeline before rendering.

### Core Configuration Parameters

| Field | Purpose | Valid Range | Default |
|-------|---------|-------------|---------|
| **`blurSteps`** | Number of Gaussian blur passes on the downscaled luminance buffer. Higher values produce smoother, more diffuse bloom at the cost of RSP cycles. | `0` to `8` | `4` |
| **`blurBrightness`** | Scalar multiplier applied to the blurred luminance before compositing. Controls bloom intensity independent of threshold. | `0.0` to `5.0` | `1.0` |
| **`hdrFactor`** | Global exposure multiplier applied during the final HDR-to-LDR tonemapping stage. Values above `1.0` brighten the entire scene; values below darken it. | `0.5` to `4.0` | `2.0` |
| **`bloomThreshold`** | Luminance cutoff value. Pixels with luminance below this threshold do not contribute to the bloom buffer, preventing dark areas from glowing artificially. | `0.0` to `1.0` | `0.2` |
| **`scalingUseRDP`** | Boolean flag selecting the downscaling implementation. When `true`, the RDP performs a fast 4:1 hardware downscale. When `false`, the RSP executes a software downscale with higher precision but greater CPU cost. | `true` / `false` | `true` |

The struct definition in [`postProcess.h`](https://github.com/HailToDodongo/pyrite64/blob/main/postProcess.h) appears as follows:

```cpp
// n64/engine/include/renderer/hdr/postProcess.h
namespace P64::Renderer::HDR {
  struct Config {
    int   blurSteps{};
    float blurBrightness{};
    float hdrFactor{};
    float bloomThreshold{};
    bool  scalingUseRDP{};
  };
}

```

## How the HDR-Bloom Pipeline Processes Your Configuration

Understanding the execution flow helps you predict the visual and performance impact of each parameter. The pipeline consumes your `Config` in three distinct stages defined across [`pipelineHDRBloom.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/pipelineHDRBloom.cpp) and [`postProcess.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/postProcess.cpp).

### Configuration Propagation

In `RenderPipelineHDRBloom::preDraw()`, the engine copies your static configuration into the per-frame `PostProcess` instance:

```cpp
// n64/engine/src/renderer/pipelineHDRBloom.cpp (lines 71-76)
postProc[frameIdx].setConf(config);
postProc[frameIdx].beginFrame();

```

### Effect Application Stages

The `PostProcess::applyEffects()` method orchestrates the post-processing chain using your parameters:

1. **Luminance Extraction & Downscale**: The engine first identifies bright pixels using `bloomThreshold`, then downscales the result 4:1 using either the RDP (if `scalingUseRDP` is `true`) or the RSP via `RspHDR::downscale()`.

2. **Iterative Blur**: The system executes `RspHDR::blur()` exactly `blurSteps` times on the downscaled buffer. Each pass applies a Gaussian kernel, with the result multiplied by `blurBrightness` before compositing.

3. **HDR Composition**: Finally, `RspHDR::hdrBlit()` combines the original frame with the blurred bloom buffer, applying the global `hdrFactor` to control final exposure.

These steps are implemented in [`postProcess.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/postProcess.cpp) (lines 16-33), with the heavy lifting delegated to `RspHDR` functions in the RSP microcode.

## Practical Fine-Tuning Strategies for Pyrite64

The following configurations demonstrate how to achieve specific visual styles while managing the performance constraints of N64 hardware.

### Maximizing Brightness and Bloom Intensity

Use this configuration for dreamlike, overexposed scenes with volumetric-style light bleeding:

```cpp
P64::Renderer::HDR::Config highBloomCfg;
highBloomCfg.blurSteps      = 5;      // Smoother, wider glow
highBloomCfg.blurBrightness = 1.5f;   // Intensify bloom contribution
highBloomCfg.hdrFactor      = 2.5f;   // Brighter overall exposure
highBloomCfg.bloomThreshold = 0.15f;  // More pixels contribute to bloom
highBloomCfg.scalingUseRDP  = true;   // Maintain performance

// Apply to the active pipeline
pipelineHDRBloom->postProc[frameIdx].setConf(highBloomCfg);

```

**Performance Note**: Each additional `blurStep` consumes approximately 1ms of RSP time on stock N64 hardware. Values above `6` may cause frame drops in complex scenes.

### Achieving Sharper Highlights with Minimal Bloom

For realistic lighting that preserves detail while adding subtle glow to only the brightest specular highlights:

```cpp
P64::Renderer::HDR::Config subtleCfg;
subtleCfg.blurSteps      = 1;      // Single blur pass for tight halo
subtleCfg.blurBrightness = 0.5f;   // Dim bloom contribution
subtleCfg.hdrFactor      = 1.2f;   // Near-neutral exposure
subtleCfg.bloomThreshold = 0.4f;   // Only brightest 40% luminance blooms
subtleCfg.scalingUseRDP  = false; // RSP downscale for sharper luminance extraction

pipelineHDRBloom->postProc[frameIdx].setConf(subtleCfg);

```

Disabling `scalingUseRDP` trades performance for precision, preventing the RDP's aggressive filtering from bleeding dark pixels into the bloom buffer.

### Performance-Optimized Settings for Lower-End Hardware

When targeting 20-30fps on complex scenes or stock Nintendo 64 consoles without expansion packs:

```cpp
P64::Renderer::HDR::Config perfCfg;
perfCfg.blurSteps      = 0;      // Skip blur entirely, HDR only
perfCfg.blurBrightness = 0.0f;   // No bloom contribution
perfCfg.hdrFactor      = 1.8f;   // Moderate exposure boost
perfCfg.bloomThreshold = 1.0f;   // Irrelevant with blurSteps=0
perfCfg.scalingUseRDP  = true;   // Fastest downscale path

pipelineHDRBloom->postProc[frameIdx].setConf(perfCfg);

```

This configuration retains the dynamic range expansion of HDR while eliminating the costly Gaussian blur passes, typically saving 4-5ms per frame.

## Real-Time Adjustment via the Editor

Pyrite64 includes a **Scene Inspector** panel that exposes these parameters without requiring code recompilation. Located in [`src/editor/pages/parts/sceneInspector.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/src/editor/pages/parts/sceneInspector.cpp), the panel provides sliders bound directly to the `Config` struct fields.

When you select the **"HDR-Bloom"** preset in the editor, the system automatically populates UI controls for `blurSteps`, `blurBrightness`, `hdrFactor`, `bloomThreshold`, and `scalingUseRDP`. Adjusting these sliders writes the new configuration into the active pipeline's `postProc` instance immediately, allowing you to fine-tune the HDR and Bloom rendering post-processing effects in real-time while observing the visual results in the viewport.

## Summary

- **Configuration Location**: Define settings in the `P64::Renderer::HDR::Config` struct found in [`n64/engine/include/renderer/hdr/postProcess.h`](https://github.com/HailToDodongo/pyrite64/blob/main/n64/engine/include/renderer/hdr/postProcess.h).
- **Default Values**: Set in [`n64/engine/src/renderer/pipelineHDRBloom.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/n64/engine/src/renderer/pipelineHDRBloom.cpp) with `blurSteps=4`, `hdrFactor=2.0`, and `scalingUseRDP=true`.
- **Application Method**: Call `postProc[frameIdx].setConf(config)` inside `RenderPipelineHDRBloom::preDraw()` before rendering.
- **Performance Trade-offs**: Each `blurStep` adds ~1ms RSP time; disabling `scalingUseRDP` improves precision but increases CPU load.
- **Visual Controls**: Use `hdrFactor` for exposure, `bloomThreshold` for highlight selectivity, and `blurBrightness` for glow intensity.

## Frequently Asked Questions

### What is the default HDR factor in Pyrite64 and how does it affect the image?

The default `hdrFactor` is `2.0` as defined in [`pipelineHDRBloom.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/pipelineHDRBloom.cpp). This value acts as an exposure multiplier during the final tonemapping stage in `RspHDR::hdrBlit()`. Values above `2.0` brighten the entire scene and expand the dynamic range, while values below `1.0` darken the image and compress highlights toward standard dynamic range.

### How many blur steps should I use for high-quality bloom effects?

For production-quality results on Nintendo 64 hardware, set `blurSteps` between `4` and `6`. The default value of `4` provides a good balance between visual smoothness and performance, consuming approximately 4ms of RSP time. Values above `6` produce only marginal visual improvements while risking frame drops, and values below `2` result in visibly boxy or banded bloom artifacts.

### Does disabling RDP scaling improve visual quality?

Setting `scalingUseRDP` to `false` can improve visual quality in scenes with fine detail or high-contrast edges. When enabled, the RDP performs a fast hardware downscale that may bleed dark pixels into the bloom buffer due to its fixed-point filtering. Disabling it routes the downscale through `RspHDR::downscale()` on the RSP, which uses more precise calculations at the cost of increased CPU utilization and approximately 0.5-1ms additional frame time.

### Where can I adjust HDR settings without recompiling the Pyrite64 engine?

You can adjust HDR and Bloom parameters in real-time using the **Scene Inspector** panel in the Pyrite64 editor, located in [`src/editor/pages/parts/sceneInspector.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/src/editor/pages/parts/sceneInspector.cpp). Select the **"HDR-Bloom"** preset to expose sliders for `hdrFactor`, `blurBrightness`, `bloomThreshold`, and other parameters. Changes apply immediately to the active `postProc` instance, allowing you to fine-tune the visual quality while observing the results in the editor viewport without modifying source code or restarting the application.