Header menu logo Mibo

Post-Processing

Post-processing runs after main scene render. Configure via PipelineConfig.

Bloom

Creates soft glow around bright pixels.

type BloomConfig = {
  Threshold: float32
  Intensity: float32
  Scatter: float32
}

Threshold: Minimum brightness for bloom contribution. Pixels below this don't glow. Typical: 0.8 - 1.2.

Intensity: Overall glow brightness. Higher = more visible.

Scatter: Glow spread distance. Higher = wider, softer bloom.

Enable bloom:

let bloomConfig = {
    Threshold = 1.0f
    Intensity = 0.5f
    Scatter = 0.7f
}

let config =
  PipelineConfig.defaults
  |> PipelineConfig.withPostProcess {
      PostProcessConfig.defaults with
          Bloom = ValueSome bloomConfig
    }

Use cases: - Glowing projectiles/spells - Neon lights, lasers - HDR bloom for bright surfaces - Dreamy/mystical atmosphere

Performance: Bloom adds full-screen blur pass. Cost increases with Scatter.

Tone Mapping

Maps HDR colors to displayable LDR range.

type ToneMappingConfig =
  | NoToneMapping
  | Reinhard
  | ACES
  | Filmic
  | AgX

NoToneMapping: Values clip at white. Fastest.

Reinhard: Simple classic algorithm. Good contrast rolloff.

ACES: Industry standard. Excellent color reproduction, cinematic.

Filmic: Good highlight rolloff, preserves shadow detail.

AgX: Modern film-inspired. Pleasant color grading.

Configure:

let config =
  PipelineConfig.defaults
  |> PipelineConfig.withPostProcess {
      PostProcessConfig.defaults with
          ToneMapping = ToneMappingConfig.ACES
    }

When to use: - Use ACES or Filmic for cinematic games - Use NoToneMapping for stylized/cartoon look (control highlights manually) - Use Reinhard for older aesthetic or simpler feel

SSAO (Screen Space Ambient Occlusion)

Darkens corners and crevices where geometry is close together.

type SSAOConfig = {
  Radius: float32
  Intensity: float32
  SampleCount: int
}

Radius: Sampling radius in world units. Larger = more coverage, may include distant geometry.

Intensity: AO strength. Higher = darker, more pronounced.

SampleCount: Samples per pixel. More = better quality, higher cost.

Enable SSAO:

let ssaoConfig = {
    Radius = 0.5f
    Intensity = 1.0f
    SampleCount = 16
}

let config =
  PipelineConfig.defaults
  |> PipelineConfig.withPostProcess {
      PostProcessConfig.defaults with
          SSAO = ValueSome ssaoConfig
    }

Use cases: - Indoor scenes (contact shadows on walls/floors) - Dense environments (forests, caves, cities) - Realistic depth perception

Performance: SSAO adds full-screen sampling pass. Cost scales with SampleCount.

Post-Process Config

type PostProcessConfig = {
  SSAO: SSAOConfig voption
  Bloom: BloomConfig voption
  ToneMapping: ToneMappingConfig
}

Combine effects:

let fullPostProcess = {
    SSAO = ValueSome {
        Radius = 0.4f
        Intensity = 0.8f
        SampleCount = 12
    }
    Bloom = ValueSome {
        Threshold = 0.9f
        Intensity = 0.4f
        Scatter = 0.6f
    }
    ToneMapping = ToneMappingConfig.Filmic
}

let config =
  PipelineConfig.defaults
  |> PipelineConfig.withPostProcess (ValueSome fullPostProcess)

Render Target Management

Post-processing requires render target allocation:

No manual management needed. Pipeline handles automatically.

See also: Lighting, Materials

type BloomConfig = { Threshold: float32 Intensity: float32 Scatter: float32 }
Multiple items
val float32: value: 'T -> float32 (requires member op_Explicit)

--------------------
type float32 = System.Single

--------------------
type float32<'Measure> = float32
val bloomConfig: BloomConfig
val config: obj
union case ValueOption.ValueSome: 'T -> ValueOption<'T>
type ToneMappingConfig = | NoToneMapping | Reinhard | ACES | Filmic | AgX
union case ToneMappingConfig.ACES: ToneMappingConfig
type SSAOConfig = { Radius: float32 Intensity: float32 SampleCount: int }
Multiple items
val int: value: 'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
val ssaoConfig: SSAOConfig
type PostProcessConfig = { SSAO: SSAOConfig voption Bloom: BloomConfig voption ToneMapping: ToneMappingConfig }
type 'T voption = ValueOption<'T>
val fullPostProcess: PostProcessConfig
union case ToneMappingConfig.Filmic: ToneMappingConfig

Type something to start searching.