nightshade-api 0.53.0

Procedural high level API for the nightshade game engine
Documentation
//! Background, grid, fog, bloom, time of day, and other scene wide settings.

use crate::runner::{SUN_NAME, lookup_named};
use nightshade::prelude::*;
use nightshade::render::config::DepthOfField;
use serde::{Deserialize, Serialize};

/// The tonemapping curve that maps HDR color to the display. `Aces` is the
/// filmic default. `Reinhard`, `ReinhardExtended`, `Uncharted2`, `AgX`,
/// `Neutral`, and `None` are the alternatives.
pub use nightshade::render::config::TonemapAlgorithm as Tonemap;

/// What fills the space behind your scene.
#[derive(Clone, Debug, Serialize, Deserialize, enum2schema::Schema)]
pub enum Background {
    /// The procedural sky gradient. The default.
    Sky,
    /// The sky with volumetric clouds.
    CloudySky,
    /// A procedural starfield.
    Space,
    /// A procedural nebula with stars.
    Nebula,
    /// A procedural sunset gradient.
    Sunset,
    /// A solid color, linear RGBA.
    Color([f32; 4]),
    /// An equirectangular hdr image used as a skybox.
    Hdr(Vec<u8>),
}

/// Sets the background. [`Background::Color`] switches the atmosphere off and
/// sets the clear color together, which is the pairing the engine needs. The
/// procedural skies recapture image based lighting automatically so
/// reflective surfaces pick up the new sky.
pub fn set_background(world: &mut World, background: Background) {
    let settings = &mut world.resources.render_settings;
    match background {
        Background::Sky => settings.atmosphere = Atmosphere::Sky,
        Background::CloudySky => settings.atmosphere = Atmosphere::CloudySky,
        Background::Space => settings.atmosphere = Atmosphere::Space,
        Background::Nebula => settings.atmosphere = Atmosphere::Nebula,
        Background::Sunset => settings.atmosphere = Atmosphere::Sunset,
        Background::Color(color) => {
            settings.atmosphere = Atmosphere::None;
            settings.clear_color = color;
        }
        Background::Hdr(bytes) => {
            load_hdr_skybox(world, bytes);
        }
    }
}

/// Shows or hides the reference grid. On by default.
#[inline]
pub fn show_grid(world: &mut World, enabled: bool) {
    world.resources.debug_draw.show_grid = enabled;
}

/// Sets the ambient light color, linear RGBA.
#[inline]
pub fn set_ambient(world: &mut World, color: [f32; 4]) {
    world.resources.render_settings.ambient_light = color;
}

/// Sets the clear color the renderer uses for the clear pass, linear RGBA.
#[inline]
pub fn set_clear_color(world: &mut World, color: [f32; 4]) {
    world.resources.render_settings.clear_color = color;
}

/// Enables distance fog between `Fog::start` and `Fog::end`, or disables it
/// with `None`.
#[inline]
pub fn set_fog(world: &mut World, fog: Option<Fog>) {
    world.resources.render_settings.fog = fog;
}

/// Toggles bloom. Emissive materials glow when this is on.
#[inline]
pub fn set_bloom(world: &mut World, enabled: bool) {
    world.resources.render_settings.bloom_enabled = enabled;
}

/// Sets the bloom strength. The default is 0.5: lower keeps the glow subtle,
/// higher blooms hard. Has no visible effect unless [`set_bloom`] is on.
#[inline]
pub fn set_bloom_intensity(world: &mut World, intensity: f32) {
    world.resources.render_settings.bloom_intensity = intensity;
}

/// Sets the hour of the day from 0.0 to 24.0. Switches the sky to the day
/// and night atmosphere and puts the default sun under its control, so the
/// sun arcs and the light warms and cools with the hour. The hour you pass is
/// authoritative, so call this every frame to animate time.
pub fn set_time_of_day(world: &mut World, hour: f32) {
    if world
        .resources
        .renderer_state
        .day_night
        .sun_entity
        .is_none()
    {
        world.resources.renderer_state.day_night.sun_entity =
            lookup_named(world, SUN_NAME).map(render_entity);
    }
    world.resources.render_settings.atmosphere = Atmosphere::DayNight;
    world.resources.renderer_state.day_night.auto_cycle = true;
    world.resources.renderer_state.day_night.speed = 0.0;
    world.resources.renderer_state.day_night.hour = hour;
}

/// Sets the manual exposure multiplier. 1.0 is neutral, above brightens,
/// below darkens.
#[inline]
pub fn set_exposure(world: &mut World, exposure: f32) {
    world.resources.render_settings.color_grading.exposure = exposure;
}

/// Sets depth of field. The engine ships presets: `DepthOfField::portrait()`,
/// `cinematic()`, `macro_shot()`, `landscape()`, and `tilt_shift()`. Disable
/// it by passing a default with `enabled` false.
#[inline]
pub fn set_depth_of_field(world: &mut World, depth_of_field: DepthOfField) {
    world.resources.render_settings.depth_of_field = depth_of_field;
}

/// Toggles screen-space ambient occlusion, the contact shadowing that darkens
/// creases and where objects meet.
#[inline]
pub fn set_ssao(world: &mut World, enabled: bool) {
    world.resources.render_settings.ssao_enabled = enabled;
}

/// Toggles screen-space reflections on glossy surfaces.
#[inline]
pub fn set_ssr(world: &mut World, enabled: bool) {
    world.resources.render_settings.ssr_enabled = enabled;
}

/// Toggles screen-space global illumination, one screen-space bounce of indirect
/// light between surfaces.
#[inline]
pub fn set_ssgi(world: &mut World, enabled: bool) {
    world.resources.render_settings.ssgi_enabled = enabled;
}

/// Toggles temporal antialiasing. Off by default.
#[inline]
pub fn set_taa(world: &mut World, enabled: bool) {
    world.resources.render_settings.taa_enabled = enabled;
}

/// Sets the tonemapping curve that maps HDR to the display.
#[inline]
pub fn set_tonemap(world: &mut World, tonemap: Tonemap) {
    world
        .resources
        .render_settings
        .color_grading
        .tonemap_algorithm = tonemap;
}

/// Sets color grading. `saturation` and `contrast` are multipliers where 1.0 is
/// neutral, `brightness` is an offset where 0.0 is neutral.
#[inline]
pub fn set_color_grading(world: &mut World, saturation: f32, contrast: f32, brightness: f32) {
    let grading = &mut world.resources.render_settings.color_grading;
    grading.saturation = saturation;
    grading.contrast = contrast;
    grading.brightness = brightness;
}

/// Saves a screenshot of the next rendered frame to `path` as a png.
pub fn screenshot(world: &mut World, path: std::path::PathBuf) {
    queue_render_command(
        world,
        RenderCommand::CaptureScreenshot {
            path: Some(path),
            max_dimension: None,
        },
    );
}