22 APR 2026

rahulmnavneeth

environment

homedocs

Location

include/mop/core/environment.h   — Public API
src/core/environment.c           — HDRI loading, IBL precompute, sky model

Types

MopEnvironmentType

typedef enum MopEnvironmentType {
    MOP_ENV_NONE            = 0,
    MOP_ENV_GRADIENT        = 1,   /* default gradient background */
    MOP_ENV_HDRI            = 2,   /* equirectangular .hdr / .exr */
    MOP_ENV_PROCEDURAL_SKY  = 3,   /* analytical sky model */
} MopEnvironmentType;

MopEnvironmentDesc

typedef struct MopEnvironmentDesc {
    MopEnvironmentType type;
    const char *hdr_path;    /* MOP_ENV_HDRI only; .hdr or .exr */
    float rotation;          /* Y-axis rotation, radians */
    float intensity;         /* brightness multiplier, default 1.0 */
} MopEnvironmentDesc;

MopProceduralSkyDesc

typedef struct MopProceduralSkyDesc {
    MopVec3 sun_direction;
    float   turbidity;       /* atmospheric turbidity [2, 10] */
    float   ground_albedo;   /* ground reflectivity [0, 1]    */
} MopProceduralSkyDesc;

Functions

mop_viewport_set_environment

bool mop_viewport_set_environment(MopViewport *vp,
                                  const MopEnvironmentDesc *desc);

Set the active environment. Returns false if the HDRI path cannot be loaded; in that case the viewport falls back to the gradient sky. The first frame after set_environment is slower because IBL maps are generated (see below).

mop_viewport_set_environment_rotation / _intensity

void mop_viewport_set_environment_rotation (MopViewport *vp, float rotation);
void mop_viewport_set_environment_intensity(MopViewport *vp, float intensity);

Adjust rotation / brightness at runtime without regenerating IBL maps.

mop_viewport_set_environment_background

void mop_viewport_set_environment_background(MopViewport *vp, bool show);

Toggle whether the HDRI is drawn as the skybox. When false the environment is still sampled for IBL but the background uses the theme gradient. Default: false.

mop_viewport_set_procedural_sky

void mop_viewport_set_procedural_sky(MopViewport *vp,
                                     const MopProceduralSkyDesc *desc);

Only meaningful when the active type is MOP_ENV_PROCEDURAL_SKY. Uses the Preetham analytical sky model rendered to a 512×256 equirectangular map, then fed through the same IBL convolution pipeline as HDRI.

IBL Precomputation

On MOP_ENV_HDRI or MOP_ENV_PROCEDURAL_SKY, three maps are precomputed and uploaded:

MapSizeUse
Irradiance64 × 32Diffuse IBL (cosine-weighted)
Prefiltered specular128 × 64, 5 mip levelsGGX specular IBL (per-roughness)
BRDF LUT256 × 256Split-sum approximation factor

These maps are sampled on both CPU and Vulkan backends. GGX importance sampling is used for the specular map.

Auto-Exposure

When an HDRI is loaded, MOP computes the log-average luminance of the image and auto-tunes mop_viewport_set_exposure so the mean maps to 0.18 (middle gray) after ACES tonemapping. Clamped to [0.01, 16.0]. Logged at INFO level. Override anytime with mop_viewport_set_exposure.

Usage

mop_viewport_set_environment(vp, &(MopEnvironmentDesc){
    .type      = MOP_ENV_HDRI,
    .hdr_path  = "studio_sunset_4k.exr",
    .rotation  = 0.0f,
    .intensity = 1.0f,
});
mop_viewport_set_environment_background(vp, true);

/* Procedural: */
mop_viewport_set_environment(vp, &(MopEnvironmentDesc){
    .type = MOP_ENV_PROCEDURAL_SKY, .intensity = 1.0f,
});
mop_viewport_set_procedural_sky(vp, &(MopProceduralSkyDesc){
    .sun_direction = {0.3f, 0.8f, 0.5f},
    .turbidity     = 3.0f,
    .ground_albedo = 0.2f,
});

See Also