mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
245 lines
8.4 KiB
Rust
245 lines
8.4 KiB
Rust
// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
// copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
// SOFTWARE.
|
|
|
|
//! Contains all structures and methods to create and manage lights.
|
|
//!
|
|
//! Light sources arte basic building blocks of many scenes in games, it improves
|
|
//! perception of scene and makes it look natural. Fyrox engine supports three kinds
|
|
//! of light sources:
|
|
//!
|
|
//! 1) Directional - similar to sun in real life, its rays are parallel.
|
|
//! 2) Spot - similar to flash light, it has cone light volume and circle spot.
|
|
//! 3) Point - similar to light bulb, it has spherical light volume.
|
|
//!
|
|
//! Each kind of light source is suitable for specific conditions, for example
|
|
//! spot light can be used if you have a character with flashlight, point - if
|
|
//! you have a character with torch, and finally directional - for outdoor light.
|
|
//!
|
|
//! Most of light sources supports shadows (via shadows maps) and light scattering,
|
|
//! these are common effects for modern games but still can significantly impact
|
|
//! performance.
|
|
|
|
use crate::{
|
|
core::{
|
|
algebra::Vector3,
|
|
color::Color,
|
|
reflect::prelude::*,
|
|
variable::InheritableVariable,
|
|
visitor::{Visit, VisitResult, Visitor},
|
|
},
|
|
scene::base::{Base, BaseBuilder},
|
|
};
|
|
use std::ops::{Deref, DerefMut};
|
|
|
|
pub mod directional;
|
|
pub mod point;
|
|
pub mod spot;
|
|
|
|
/// Default amount of light scattering, it is set to 3% which is fairly
|
|
/// significant value and you'll clearly see light volume with such settings.
|
|
pub const DEFAULT_SCATTER_R: f32 = 0.03;
|
|
|
|
/// Default amount of light scattering, it is set to 3% which is fairly
|
|
/// significant value and you'll clearly see light volume with such settings.
|
|
pub const DEFAULT_SCATTER_G: f32 = 0.03;
|
|
|
|
/// Default amount of light scattering, it is set to 3% which is fairly
|
|
/// significant value and you'll clearly see light volume with such settings.
|
|
pub const DEFAULT_SCATTER_B: f32 = 0.03;
|
|
|
|
/// Light scene node. It contains common properties of light such as color,
|
|
/// scattering factor (per color channel) and other useful properties. Exact
|
|
/// behavior defined by specific light kind.
|
|
#[derive(Debug, Reflect, Clone, Visit)]
|
|
#[reflect(type_uuid = "5c9486ed-5f3b-4225-bed5-95f9bde6360e")]
|
|
pub struct BaseLight {
|
|
base: Base,
|
|
|
|
#[reflect(setter = "set_color")]
|
|
color: InheritableVariable<Color>,
|
|
|
|
#[visit(rename = "ScatterFactor")]
|
|
#[reflect(setter = "set_scatter")]
|
|
scatter: InheritableVariable<Vector3<f32>>,
|
|
|
|
#[reflect(setter = "enable_scatter")]
|
|
scatter_enabled: InheritableVariable<bool>,
|
|
|
|
#[reflect(min_value = 0.0, step = 0.1)]
|
|
#[reflect(setter = "set_intensity")]
|
|
intensity: InheritableVariable<f32>,
|
|
}
|
|
|
|
impl Deref for BaseLight {
|
|
type Target = Base;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.base
|
|
}
|
|
}
|
|
|
|
impl DerefMut for BaseLight {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.base
|
|
}
|
|
}
|
|
|
|
impl Default for BaseLight {
|
|
fn default() -> Self {
|
|
Self {
|
|
base: Default::default(),
|
|
color: InheritableVariable::new_modified(Color::WHITE),
|
|
scatter: InheritableVariable::new_modified(Vector3::new(
|
|
DEFAULT_SCATTER_R,
|
|
DEFAULT_SCATTER_G,
|
|
DEFAULT_SCATTER_B,
|
|
)),
|
|
scatter_enabled: InheritableVariable::new_modified(true),
|
|
intensity: InheritableVariable::new_modified(1.0),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl BaseLight {
|
|
/// Sets color of light, alpha component of color is ignored.
|
|
#[inline]
|
|
pub fn set_color(&mut self, color: Color) -> Color {
|
|
self.color.set_value_and_mark_modified(color)
|
|
}
|
|
|
|
/// Returns current color of light source.
|
|
#[inline]
|
|
pub fn color(&self) -> Color {
|
|
*self.color
|
|
}
|
|
|
|
/// Sets scatter factor per color channel (red, green, blue) in (0..1) range.
|
|
/// This parameter defines how "thick" environment is and how much light will
|
|
/// be scattered in light volume. Ability to change this parameter per channel
|
|
/// allows you simulate Rayleigh scatter if needed - in simple words Rayleigh
|
|
/// scatter tells us that blue light waves scatters much better than red ones,
|
|
/// this effect makes sky blue. Reasonable value is something near 0.024-0.03
|
|
/// per color channel, higher values will cause too "heavy" light scattering
|
|
/// as if you light source would be in fog.
|
|
#[inline]
|
|
pub fn set_scatter(&mut self, f: Vector3<f32>) -> Vector3<f32> {
|
|
self.scatter.set_value_and_mark_modified(f)
|
|
}
|
|
|
|
/// Returns current scatter factor.
|
|
#[inline]
|
|
pub fn scatter(&self) -> Vector3<f32> {
|
|
*self.scatter
|
|
}
|
|
|
|
/// Sets new light intensity. Default is 1.0.
|
|
///
|
|
/// Intensity is used for very bright light sources in HDR. For examples, sun
|
|
/// can be represented as directional light source with very high intensity.
|
|
/// Other lights, however, will remain relatively dim.
|
|
pub fn set_intensity(&mut self, intensity: f32) -> f32 {
|
|
self.intensity.set_value_and_mark_modified(intensity)
|
|
}
|
|
|
|
/// Returns current intensity of the light.
|
|
pub fn intensity(&self) -> f32 {
|
|
*self.intensity
|
|
}
|
|
|
|
/// Returns current scatter factor in linear color space.
|
|
#[inline]
|
|
pub fn scatter_linear(&self) -> Vector3<f32> {
|
|
self.scatter.map(|v| v.powf(2.2))
|
|
}
|
|
|
|
/// Enables or disables light scattering.
|
|
#[inline]
|
|
pub fn enable_scatter(&mut self, state: bool) -> bool {
|
|
self.scatter_enabled.set_value_and_mark_modified(state)
|
|
}
|
|
|
|
/// Returns true if light scattering is enabled, false - otherwise.
|
|
#[inline]
|
|
pub fn is_scatter_enabled(&self) -> bool {
|
|
*self.scatter_enabled
|
|
}
|
|
}
|
|
|
|
/// Light scene node builder. Provides easy declarative way of creating light scene
|
|
/// nodes.
|
|
pub struct BaseLightBuilder {
|
|
base_builder: BaseBuilder,
|
|
color: Color,
|
|
scatter_factor: Vector3<f32>,
|
|
scatter_enabled: bool,
|
|
intensity: f32,
|
|
}
|
|
|
|
impl BaseLightBuilder {
|
|
/// Creates new instance of light scene node builder, you must pass desired
|
|
/// light kind and base scene node builder as parameters. Latter one is needed
|
|
/// because engine uses composition and light scene node built on top of base
|
|
/// scene node.
|
|
pub fn new(base_builder: BaseBuilder) -> Self {
|
|
Self {
|
|
base_builder,
|
|
color: Color::WHITE,
|
|
scatter_factor: Vector3::new(DEFAULT_SCATTER_R, DEFAULT_SCATTER_G, DEFAULT_SCATTER_B),
|
|
scatter_enabled: true,
|
|
intensity: 1.0,
|
|
}
|
|
}
|
|
|
|
/// Sets light color.
|
|
pub fn with_color(mut self, color: Color) -> Self {
|
|
self.color = color;
|
|
self
|
|
}
|
|
|
|
/// Sets light scatter factor per color channel.
|
|
pub fn with_scatter_factor(mut self, f: Vector3<f32>) -> Self {
|
|
self.scatter_factor = f;
|
|
self
|
|
}
|
|
|
|
/// Whether light scatter enabled or not.
|
|
pub fn with_scatter_enabled(mut self, state: bool) -> Self {
|
|
self.scatter_enabled = state;
|
|
self
|
|
}
|
|
|
|
/// Sets desired light intensity.
|
|
pub fn with_intensity(mut self, intensity: f32) -> Self {
|
|
self.intensity = intensity;
|
|
self
|
|
}
|
|
|
|
/// Creates new instance of base light.
|
|
pub fn build(self) -> BaseLight {
|
|
BaseLight {
|
|
base: self.base_builder.build_base(),
|
|
color: self.color.into(),
|
|
scatter: self.scatter_factor.into(),
|
|
scatter_enabled: self.scatter_enabled.into(),
|
|
intensity: self.intensity.into(),
|
|
}
|
|
}
|
|
}
|