Light node

The engine offers complex lighting system with various types of light sources.

Light types

There are three main types of light sources: directional, point, and spotlights.

Directional light

Directional light does not have a position, its rays are always parallel, and it has a particular direction in space. An example of directional light in real-life could be our Sun. Even if it is a point light, it is so far away from the Earth, so we can assume that its rays are always parallel. Directional light sources are suitable for outdoor scenes.

A directional light source could be created like this:

#![allow(unused)]
fn main() {
extern crate fyrox;
use fyrox::{
    core::pool::Handle,
    scene::{
        base::BaseBuilder,
        light::{directional::DirectionalLightBuilder, BaseLightBuilder},
        node::Node,
        Scene,
    },
};

fn create_directional_light(scene: &mut Scene) -> Handle<Node> {
    DirectionalLightBuilder::new(BaseLightBuilder::new(BaseBuilder::new()))
        .build(&mut scene.graph)
}
}

By default, the light source will be oriented to lit "the ground". In other words its direction will be faced towards (0.0, -1.0, 0.0) vector. You can rotate it as you want by setting local transform of it while building. Something like this:

#![allow(unused)]
fn main() {
extern crate fyrox;
use fyrox::{
    core::{
        algebra::{UnitQuaternion, Vector3},
        pool::Handle,
    },
    scene::{
        base::BaseBuilder,
        light::{directional::DirectionalLightBuilder, BaseLightBuilder},
        node::Node,
        transform::TransformBuilder,
        Scene,
    },
};

fn create_directional_light(scene: &mut Scene) -> Handle<Node> {
    DirectionalLightBuilder::new(BaseLightBuilder::new(
        BaseBuilder::new().with_local_transform(
            TransformBuilder::new()
                .with_local_rotation(UnitQuaternion::from_axis_angle(
                    &Vector3::x_axis(),
                    -45.0f32.to_radians(),
                ))
                .build(),
        ),
    ))
    .build(&mut scene.graph)
}
}

Point light

Point light is a light source that emits lights in all directions, it has a position, but does not have an orientation. An example of a point light source: light bulb.

#![allow(unused)]
fn main() {
extern crate fyrox;
use fyrox::{
    core::pool::Handle,
    scene::{
        base::BaseBuilder,
        light::{point::PointLightBuilder, BaseLightBuilder},
        node::Node,
        Scene,
    },
};

fn create_point_light(scene: &mut Scene) -> Handle<Node> {
    PointLightBuilder::new(BaseLightBuilder::new(BaseBuilder::new()))
        .with_radius(5.0)
        .build(&mut scene.graph)
}
}

Spotlight

Spotlight is a light source that emits lights in cone shape, it has a position and orientation. An example of a spotlight source: flashlight.

#![allow(unused)]
fn main() {
extern crate fyrox;
use fyrox::{
    core::pool::Handle,
    scene::{
        base::BaseBuilder,
        light::{spot::SpotLightBuilder, BaseLightBuilder},
        node::Node,
        Scene,
    },
};

fn create_spot_light(scene: &mut Scene) -> Handle<Node> {
    SpotLightBuilder::new(BaseLightBuilder::new(BaseBuilder::new()))
        .with_distance(5.0)
        .with_hotspot_cone_angle(50.0f32.to_radians())
        .with_falloff_angle_delta(10.0f32.to_radians())
        .build(&mut scene.graph)
}
}

Light scattering

scattering

Spot and point lights support light scattering effect. Imagine you're walking with a flashlight in a foggy weather, the fog will scatter the light from your flashlight making it, so you'll see the "light volume". Light scattering is enabled by default, so you don't have to do anything to enable it. However, in some cases you might want to disable it, you can do this either while building a light source or change light scattering options on existing light source. Here is the small example of how to do that.

#![allow(unused)]
fn main() {
extern crate fyrox;
use fyrox::{
    core::pool::Handle,
    scene::{node::Node, light::BaseLight, Scene},
};

fn disable_light_scatter(scene: &mut Scene, light_handle: Handle<Node>) {
    scene.graph[light_handle]
        .query_component_mut::<BaseLight>()
        .unwrap()
        .enable_scatter(false);
}
}

You could also change the amount of scattering per each color channel, using this you could imitate the Rayleigh scattering:

#![allow(unused)]
fn main() {
extern crate fyrox;
use fyrox::{
    core::{algebra::Vector3, pool::Handle},
    scene::{node::Node, light::BaseLight, Scene},
};

fn use_rayleigh_scattering(scene: &mut Scene, light_handle: Handle<Node>) {
    scene.graph[light_handle]
        .query_component_mut::<BaseLight>()
        .unwrap()
        .set_scatter(Vector3::new(0.03, 0.035, 0.055));
}
}

Shadows

By default, light sources cast shadows. You can change this by using set_cast_shadows method of a light source. You should carefully manage shadows: shadows giving the most significant performance impact, you should keep the amount of light sources that can cast shadows at lowest possible amount to keep performance at good levels. You can also turn on/off shadows when you need:

#![allow(unused)]
fn main() {
extern crate fyrox;
use fyrox::{
    core::pool::Handle,
    scene::{node::Node, light::BaseLight, Scene},
};

fn switch_shadows(scene: &mut Scene, light_handle: Handle<Node>, cast_shadows: bool) {
    scene.graph[light_handle]
        .query_component_mut::<BaseLight>()
        .unwrap()
        .set_cast_shadows(cast_shadows);
}
}

Not every light should cast shadows, for example a small light that a player can see only in a distance can have shadows disabled. You should set the appropriate values depending on your scene, just remember: the fewer the shadows the better the performance. The most expensive shadows are from point lights, the less, from spotlights and directional lights.

Performance

Lights are not cheap, every light source has some performance impact. As a general rule, try to keep the amount of light sources at reasonable levels and especially try to avoid creating tons of light sources in a small area. Keep in mind that the less area the light needs to "cover", the higher the performance. This means that you can have tons of small light sources for free.