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

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 and consumed during the frame rendering loop in 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 appears as follows:

// 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 and postProcess.cpp.

Configuration Propagation

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

// 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 (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:

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:

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:

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, 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.
  • Default Values: Set in 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. 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. 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →