Skip to main content

nightshade_api/
environment.rs

1//! Background, grid, fog, bloom, time of day, and other scene wide settings.
2
3use crate::runner::{SUN_NAME, lookup_named};
4use nightshade::prelude::*;
5use nightshade::render::config::DepthOfField;
6use serde::{Deserialize, Serialize};
7
8/// The tonemapping curve that maps HDR color to the display. `Aces` is the
9/// filmic default. `Reinhard`, `ReinhardExtended`, `Uncharted2`, `AgX`,
10/// `Neutral`, and `None` are the alternatives.
11pub use nightshade::render::config::TonemapAlgorithm as Tonemap;
12
13/// What fills the space behind your scene.
14#[derive(Clone, Debug, Serialize, Deserialize, enum2schema::Schema)]
15pub enum Background {
16    /// The procedural sky gradient. The default.
17    Sky,
18    /// The sky with volumetric clouds.
19    CloudySky,
20    /// A procedural starfield.
21    Space,
22    /// A procedural nebula with stars.
23    Nebula,
24    /// A procedural sunset gradient.
25    Sunset,
26    /// A solid color, linear RGBA.
27    Color([f32; 4]),
28    /// An equirectangular hdr image used as a skybox.
29    Hdr(Vec<u8>),
30}
31
32/// Sets the background. [`Background::Color`] switches the atmosphere off and
33/// sets the clear color together, which is the pairing the engine needs. The
34/// procedural skies recapture image based lighting automatically so
35/// reflective surfaces pick up the new sky.
36pub fn set_background(world: &mut World, background: Background) {
37    let settings = &mut world.resources.render_settings;
38    match background {
39        Background::Sky => settings.atmosphere = Atmosphere::Sky,
40        Background::CloudySky => settings.atmosphere = Atmosphere::CloudySky,
41        Background::Space => settings.atmosphere = Atmosphere::Space,
42        Background::Nebula => settings.atmosphere = Atmosphere::Nebula,
43        Background::Sunset => settings.atmosphere = Atmosphere::Sunset,
44        Background::Color(color) => {
45            settings.atmosphere = Atmosphere::None;
46            settings.clear_color = color;
47        }
48        Background::Hdr(bytes) => {
49            load_hdr_skybox(world, bytes);
50        }
51    }
52}
53
54/// Shows or hides the reference grid. On by default.
55#[inline]
56pub fn show_grid(world: &mut World, enabled: bool) {
57    world.resources.debug_draw.show_grid = enabled;
58}
59
60/// Sets the ambient light color, linear RGBA.
61#[inline]
62pub fn set_ambient(world: &mut World, color: [f32; 4]) {
63    world.resources.render_settings.ambient_light = color;
64}
65
66/// Sets the clear color the renderer uses for the clear pass, linear RGBA.
67#[inline]
68pub fn set_clear_color(world: &mut World, color: [f32; 4]) {
69    world.resources.render_settings.clear_color = color;
70}
71
72/// Enables distance fog between `Fog::start` and `Fog::end`, or disables it
73/// with `None`.
74#[inline]
75pub fn set_fog(world: &mut World, fog: Option<Fog>) {
76    world.resources.render_settings.fog = fog;
77}
78
79/// Toggles bloom. Emissive materials glow when this is on.
80#[inline]
81pub fn set_bloom(world: &mut World, enabled: bool) {
82    world.resources.render_settings.bloom_enabled = enabled;
83}
84
85/// Sets the bloom strength. The default is 0.5: lower keeps the glow subtle,
86/// higher blooms hard. Has no visible effect unless [`set_bloom`] is on.
87#[inline]
88pub fn set_bloom_intensity(world: &mut World, intensity: f32) {
89    world.resources.render_settings.bloom_intensity = intensity;
90}
91
92/// Sets the hour of the day from 0.0 to 24.0. Switches the sky to the day
93/// and night atmosphere and puts the default sun under its control, so the
94/// sun arcs and the light warms and cools with the hour. The hour you pass is
95/// authoritative, so call this every frame to animate time.
96pub fn set_time_of_day(world: &mut World, hour: f32) {
97    if world
98        .resources
99        .renderer_state
100        .day_night
101        .sun_entity
102        .is_none()
103    {
104        world.resources.renderer_state.day_night.sun_entity =
105            lookup_named(world, SUN_NAME).map(render_entity);
106    }
107    world.resources.render_settings.atmosphere = Atmosphere::DayNight;
108    world.resources.renderer_state.day_night.auto_cycle = true;
109    world.resources.renderer_state.day_night.speed = 0.0;
110    world.resources.renderer_state.day_night.hour = hour;
111}
112
113/// Sets the manual exposure multiplier. 1.0 is neutral, above brightens,
114/// below darkens.
115#[inline]
116pub fn set_exposure(world: &mut World, exposure: f32) {
117    world.resources.render_settings.color_grading.exposure = exposure;
118}
119
120/// Sets depth of field. The engine ships presets: `DepthOfField::portrait()`,
121/// `cinematic()`, `macro_shot()`, `landscape()`, and `tilt_shift()`. Disable
122/// it by passing a default with `enabled` false.
123#[inline]
124pub fn set_depth_of_field(world: &mut World, depth_of_field: DepthOfField) {
125    world.resources.render_settings.depth_of_field = depth_of_field;
126}
127
128/// Toggles screen-space ambient occlusion, the contact shadowing that darkens
129/// creases and where objects meet.
130#[inline]
131pub fn set_ssao(world: &mut World, enabled: bool) {
132    world.resources.render_settings.ssao_enabled = enabled;
133}
134
135/// Toggles screen-space reflections on glossy surfaces.
136#[inline]
137pub fn set_ssr(world: &mut World, enabled: bool) {
138    world.resources.render_settings.ssr_enabled = enabled;
139}
140
141/// Toggles screen-space global illumination, one screen-space bounce of indirect
142/// light between surfaces.
143#[inline]
144pub fn set_ssgi(world: &mut World, enabled: bool) {
145    world.resources.render_settings.ssgi_enabled = enabled;
146}
147
148/// Toggles temporal antialiasing. Off by default.
149#[inline]
150pub fn set_taa(world: &mut World, enabled: bool) {
151    world.resources.render_settings.taa_enabled = enabled;
152}
153
154/// Sets the tonemapping curve that maps HDR to the display.
155#[inline]
156pub fn set_tonemap(world: &mut World, tonemap: Tonemap) {
157    world
158        .resources
159        .render_settings
160        .color_grading
161        .tonemap_algorithm = tonemap;
162}
163
164/// Sets color grading. `saturation` and `contrast` are multipliers where 1.0 is
165/// neutral, `brightness` is an offset where 0.0 is neutral.
166#[inline]
167pub fn set_color_grading(world: &mut World, saturation: f32, contrast: f32, brightness: f32) {
168    let grading = &mut world.resources.render_settings.color_grading;
169    grading.saturation = saturation;
170    grading.contrast = contrast;
171    grading.brightness = brightness;
172}
173
174/// Saves a screenshot of the next rendered frame to `path` as a png.
175pub fn screenshot(world: &mut World, path: std::path::PathBuf) {
176    queue_render_command(
177        world,
178        RenderCommand::CaptureScreenshot {
179            path: Some(path),
180            max_dimension: None,
181        },
182    );
183}