Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Add Distance and Atmospheric Fog support #6412

Closed
wants to merge 79 commits into from
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
014a9cb
Add fog support to bevy_pbr
coreh Oct 29, 2022
6458025
Add flag to `StandardMaterial` to disable fog
coreh Oct 29, 2022
dfbd7f6
Add fog documentation
coreh Oct 29, 2022
d7afc3e
Fix example code that's failing on CI
coreh Oct 29, 2022
fb588a5
Add additional fog documentation
coreh Oct 30, 2022
0d2afb9
Make `Fog` a `Component` instead of a `Resource`
coreh Nov 1, 2022
8855bdd
Consolidate fog-related setup into `FogPlugin`
coreh Nov 1, 2022
f7fb67e
Fix example code that's failing on CI
coreh Nov 1, 2022
8c8aa79
Remove `FogMode::Off`
coreh Nov 2, 2022
d999308
Add Fog example
coreh Nov 2, 2022
c446fcc
Fix clippy issues
coreh Nov 2, 2022
2138dfc
Apply feedback on example and fix mismatched variable names
coreh Nov 3, 2022
b7c478f
Add controls table to example module documentation
coreh Nov 3, 2022
db1eca0
Add semicolon
coreh Nov 3, 2022
1e7f6c3
Merge branch 'main' into fog
coreh Nov 3, 2022
6b8a196
Rename fog component and falloff enum, for consistency and reusability
coreh Nov 3, 2022
6d2a41a
Add initial implementation of atmospheric fog and directional light s…
coreh Nov 3, 2022
7de98fd
Fix documentation broken/missing links
coreh Nov 3, 2022
505a5a2
Fix example code now that there are more fog settings
coreh Nov 3, 2022
e13c5c3
Fix clippy issue
coreh Nov 3, 2022
5d8f708
Fix the spelling of the word ‘exponent’
coreh Nov 4, 2022
e7a4a98
Use `Time::elapsed_seconds()` and `Time::delta_seconds()`
coreh Nov 4, 2022
ddb4eb9
Improve documentation, in response to PR feedback
coreh Nov 4, 2022
48295a0
Improve `GpuFog` documentation comments
coreh Nov 4, 2022
7a88d0e
Optimize/cleanup shader code
coreh Nov 4, 2022
50f0f50
Take directional light colors into account for scattering
coreh Nov 4, 2022
00226a3
Rename `scattering_color` to `directional_light_color`
coreh Nov 4, 2022
e18f682
Merge branch 'main' into fog
coreh Nov 4, 2022
e4f01e2
Merge branch 'main' into fog
coreh Nov 4, 2022
e626862
Add atmospheric fog example
coreh Nov 4, 2022
270dcd9
Fix clippy issue
coreh Nov 4, 2022
8ecba3b
Add methods for more easily configuring atmospheric fog
coreh Nov 4, 2022
68447a2
Use new visibility helper method in atmospheric fog example
coreh Nov 4, 2022
a2a5b07
Improve documentation
coreh Nov 4, 2022
a4ee547
Use `Vec3` instead of `Color` for extinction and inscattering
coreh Nov 4, 2022
e0195d3
Improve documentation
coreh Nov 4, 2022
e830d93
Add convenience methods for `FogFalloff::ExponentialSquared`
coreh Nov 4, 2022
a998fa8
Tweaks to documentation formatting and punctuation
coreh Nov 4, 2022
c608a75
Improve documentation
coreh Nov 4, 2022
aeafcc7
Remove misleading note about exponential density values
coreh Nov 4, 2022
ecea533
Fix clippy issue
coreh Nov 4, 2022
73ad380
Remove now-unnecessary UI camera
coreh Nov 4, 2022
3323542
Add comments explaining values
coreh Nov 4, 2022
92dac89
Fix documentation tests
coreh Nov 4, 2022
256fce6
Update examples/README.md
coreh Nov 4, 2022
be50d07
Merge branch 'main' into fog
coreh Nov 4, 2022
50a41cd
Use positive `fog_enabled` flag (instead of `no_fog`)
coreh Nov 4, 2022
a35783a
Add minor clarification that this is the color obtained after extinction
coreh Nov 4, 2022
8261011
Rename `result` to `fog_color` in shader
coreh Nov 4, 2022
11f1bb5
Fix search and replace mishap
coreh Nov 4, 2022
cbb330c
Use names consistent with documentation
coreh Nov 4, 2022
bf668da
Move fog to outside of `pbr()`, so that it applies to unlit materials
coreh Nov 4, 2022
e3b65c8
Merge branch 'main' into fog
coreh Nov 6, 2022
036fbd3
Add controls table and move system to last
coreh Nov 6, 2022
9f3b0c4
Improve documentation
coreh Nov 6, 2022
49a3f1e
Use “glow” instead of “halo” in explanation
coreh Nov 6, 2022
f9056c0
Improve documentation
coreh Nov 6, 2022
3c9b359
Fix constants typo in documentation comments
coreh Nov 8, 2022
e123574
Fix additional constant typos
coreh Nov 9, 2022
2664ca1
Merge branch 'main' into fog
coreh Nov 12, 2022
d54dce2
Reduce sky size, fixing (floating point precision?) flicker in WASM /…
coreh Nov 20, 2022
ccfb0ce
Merge branch 'main' into fog
coreh Nov 24, 2022
6ab1188
Break up long lines in WGSL shaders for readability
coreh Jan 15, 2023
f44e381
Remove incorrect claim that extinction factor is ‘unitless’ from docu…
coreh Jan 15, 2023
aa3fef7
Improve documentation wording
coreh Jan 15, 2023
f1cebd2
Increase font size in fog examples
coreh Jan 15, 2023
f9ceb4c
Merge branch 'main' into fog
coreh Jan 15, 2023
820a6b1
Merge branch 'main' into fog
coreh Jan 21, 2023
cd11d43
Make sure `apply_fog()` function is not defined during normal prepass
coreh Jan 21, 2023
df77ce3
Merge branch 'main' into fog
coreh Jan 21, 2023
15afdfb
Fix code for creating exponential squared fog
coreh Jan 28, 2023
c4eb571
Remove unused `KOSCHMIEDER_CONTRAST_THRESHOLD` constant
coreh Jan 28, 2023
28f4fb0
Tweak wording, remove trailing whitespace
coreh Jan 28, 2023
8b99f6f
Reorder `GpuFog` fields for better struct packing
coreh Jan 28, 2023
1e3ab2c
Extract repeated scattering code into function
coreh Jan 28, 2023
5fd6a42
Merge branch 'main' into fog
coreh Jan 28, 2023
8c4d4e9
Properly configure cascade shadow map for scene
coreh Jan 28, 2023
4608dbd
Use multiplication instead of `pow()` with `2.0`
coreh Jan 28, 2023
fee838d
Pass fragment and view positions and calculate `view_to_world` in `ap…
coreh Jan 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,17 @@ description = "A scene showcasing the built-in 3D shapes"
category = "3D Rendering"
wasm = true

[[example]]
name = "fog"
path = "examples/3d/fog.rs"

[package.metadata.example.fog]
name = "Fog"
description = "A scene showcasing the distance fog effect"
category = "3D Rendering"
wasm = true


[[example]]
name = "lighting"
path = "examples/3d/lighting.rs"
Expand Down
200 changes: 200 additions & 0 deletions crates/bevy_pbr/src/fog.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
use crate::ReflectComponent;
use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_reflect::Reflect;
use bevy_render::{color::Color, extract_component::ExtractComponent, prelude::Camera};

/// A “classic” computer graphics [distance fog](https://en.wikipedia.org/wiki/Distance_fog) effect, that makes
/// objects appear progressively more covered in atmospheric haze as they move further away from the camera.
/// Affects meshes rendered via the PBR [`StandardMaterial`](crate::StandardMaterial).
/// Configurable independently for each camera.
///
/// Currently, the following fog modes are supported:
///
/// - [`FogMode::Linear`]
/// - [`FogMode::Exponential`]
/// - [`FogMode::ExponentialSquared`]
///
/// ## Example
///
/// ```
/// # use bevy_ecs::prelude::*;
/// # use bevy_render::prelude::*;
/// # use bevy_core_pipeline::prelude::*;
/// # use bevy_pbr::prelude::*;
/// # fn system(mut commands: Commands) {
/// commands.spawn((
/// // Setup your camera as usual
/// Camera3dBundle {
/// // ... camera options
/// # ..Default::default()
/// },
/// // Add fog to the same entity
/// Fog {
/// color: Color::WHITE,
/// mode: FogMode::Exponential { density: 1e-3 },
/// },
/// ));
/// # }
/// # bevy_ecs::system::assert_is_system(system);
/// ```
///
/// ## Material Override
///
/// Once enabled for a specific camera, the fog effect can also be disabled for individual
/// [`StandardMaterial`](crate::StandardMaterial) instances via the `no_fog` flag.
#[derive(Debug, Clone, Component, Reflect)]
#[reflect(Component)]
pub struct Fog {
/// The color of the fog effect.
///
/// **Tip:** The alpha channel of the color can be used to “modulate” the fog effect without
/// changing the fog mode or parameters.
pub color: Color,

/// Determines which “mode” of fog rendering to use, and provides parameters for each mode.
pub mode: FogMode,
}

/// Allows switching between different the [`Fog`] “modes”, and configuring their parameters.
#[derive(Debug, Clone, Reflect)]
pub enum FogMode {
/// A linear fog effect that grows in intensity between `start` and `end` distances.
///
/// This mode is simpler to control than other modes, however it can produce results that look “artificial”, depending on the scene.
///
/// ## Formula
///
/// The fog intensity for a given point in the scene is determined by the following formula:
///
/// ```text
/// let fog_intensity = 1.0 - ((end - distance) / (end - start)).clamp(0.0, 1.0);
/// ```
///
/// <svg width="370" height="212" viewBox="0 0 370 212" fill="none">
/// <title>Plot showing how the linear fog mode behaves for start and end values of 0.8 and 2.2, respectively.</title>
/// <path d="M331 151H42V49" stroke="currentColor" stroke-width="2"/>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-family="Inter" font-size="12" letter-spacing="0em"><tspan x="136" y="173.864">1</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-family="Inter" font-size="12" letter-spacing="0em"><tspan x="30" y="53.8636">1</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-family="Inter" font-size="12" letter-spacing="0em"><tspan x="42" y="173.864">0</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-family="Inter" font-size="12" letter-spacing="0em"><tspan x="232" y="173.864">2</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-family="Inter" font-size="12" letter-spacing="0em"><tspan x="332" y="173.864">3</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-family="Inter" font-size="12" letter-spacing="0em"><tspan x="161" y="190.864">distance</tspan></text>
/// <text font-family="sans-serif" transform="translate(10 132) rotate(-90)" fill="currentColor" style="white-space: pre" font-family="Inter" font-size="12" letter-spacing="0em"><tspan x="0" y="11.8636">fog intensity</tspan></text>
/// <path d="M43 150H117.227L263 48H331" stroke="#FF00E5"/>
/// <path d="M118 151V49" stroke="#FF00E5" stroke-dasharray="1 4"/>
/// <path d="M263 151V49" stroke="#FF00E5" stroke-dasharray="1 4"/>
/// <text font-family="sans-serif" fill="#FF00E5" style="white-space: pre" font-family="Inter" font-size="10" letter-spacing="0em"><tspan x="121" y="58.6364">start</tspan></text>
/// <text font-family="sans-serif" fill="#FF00E5" style="white-space: pre" font-family="Inter" font-size="10" letter-spacing="0em"><tspan x="267" y="58.6364">end</tspan></text>
/// </svg>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL you can embed SVG graphs inside of rustdoc!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw the Color constant docs that use styled <span>s and decided to give it a try, was also pleasantly surprised

Linear {
// Distance from the camera where fog is completely transparent
start: f32,

// Distance from the camera where fog is completely opaque
end: f32,
},
coreh marked this conversation as resolved.
Show resolved Hide resolved

/// An exponential fog effect with a given `density`.
///
/// Initially gains intensity quickly with distance, then more slowly. Typically produces more natural results than [`FogMode::Linear`],
/// but is a bit harder to control.
///
/// To move the fog “further away”, use lower density values. To move it “closer” use higher density values.
///
/// **Note:** It's not _unusual_ to have very large or very small values for the density, depending on the scene
/// scale. Typically, for scenes with objects in the scale of thousands of units, you might want density values
/// in the ballpark of `1e-3`. Conversely, for really small scale scenes you might want really high values of
/// density.
///
/// **Tip:** You can combine the `density` parameter with the [`Fog`] `color`'s alpha channel for easier control.
///
/// ## Formula
///
/// The fog intensity for a given point in the scene is determined by the following formula:
///
/// ```text
/// let fog_intensity = 1.0 - 1.0 / (distance * density).exp();
/// ```
///
/// <svg width="370" height="212" viewBox="0 0 370 212" fill="none">
/// <title>Plot showing how the exponential fog mode behaves for different density values</title>
/// <mask id="mask0_3_31" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="42" y="42" width="286" height="108">
/// <rect x="42" y="42" width="286" height="108" fill="#D9D9D9"/>
/// </mask>
/// <g mask="url(#mask0_3_31)">
/// <path d="M42 150C42 150 98.3894 53 254.825 53L662 53" stroke="#FF003D" stroke-width="1"/>
/// <path d="M42 150C42 150 139.499 53 409.981 53L1114 53" stroke="#001AFF" stroke-width="1"/>
/// <path d="M42 150C42 150 206.348 53 662.281 53L1849 53" stroke="#14FF00" stroke-width="1"/>
/// </g>
/// <path d="M331 151H42V49" stroke="currentColor" stroke-width="2"/>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="136" y="173.864">1</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="30" y="53.8636">1</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="42" y="173.864">0</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="232" y="173.864">2</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="332" y="173.864">3</tspan></text>
/// <text font-family="sans-serif" fill="#FF003D" style="white-space: pre" font-size="10" letter-spacing="0em"><tspan x="77" y="64.6364">density = 2</tspan></text>
/// <text font-family="sans-serif" fill="#001AFF" style="white-space: pre" font-size="10" letter-spacing="0em"><tspan x="236" y="76.6364">density = 1</tspan></text>
/// <text font-family="sans-serif" fill="#14FF00" style="white-space: pre" font-size="10" letter-spacing="0em"><tspan x="205" y="115.636">density = 0.5</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="161" y="190.864">distance</tspan></text>
/// <text font-family="sans-serif" transform="translate(10 132) rotate(-90)" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="0" y="11.8636">fog intensity</tspan></text>
/// </svg>
Exponential { density: f32 },
coreh marked this conversation as resolved.
Show resolved Hide resolved

/// A squared exponential fog effect with a given `density`.
///
/// Similar to [`FogMode::Exponential`], but grows more slowly in intensity for closer distances
/// before “catching up”.
///
/// ## Formula
///
/// The fog intensity for a given point in the scene is determined by the following formula:
///
/// ```text
/// let fog_intensity = 1.0 - 1.0 / (distance * density).powi(2).exp();
/// ```
///
/// <svg width="370" height="212" viewBox="0 0 370 212" fill="none">
/// <title>Plot showing how the exponential squared fog mode behaves for different density values</title>
/// <mask id="mask0_1_3" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="42" y="42" width="286" height="108">
/// <rect x="42" y="42" width="286" height="108" fill="#D9D9D9"/>
/// </mask>
/// <g mask="url(#mask0_1_3)">
/// <path d="M42 150C75.4552 150 74.9241 53.1724 166.262 53.1724L404 53.1724" stroke="#FF003D" stroke-width="1"/>
/// <path d="M42 150C107.986 150 106.939 53.1724 287.091 53.1724L756 53.1724" stroke="#001AFF" stroke-width="1"/>
/// <path d="M42 150C166.394 150 164.42 53.1724 504.035 53.1724L1388 53.1724" stroke="#14FF00" stroke-width="1"/>
/// </g>
/// <path d="M331 151H42V49" stroke="currentColor" stroke-width="2"/>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="136" y="173.864">1</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="30" y="53.8636">1</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="42" y="173.864">0</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="232" y="173.864">2</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="332" y="173.864">3</tspan></text>
/// <text font-family="sans-serif" fill="#FF003D" style="white-space: pre" font-size="10" letter-spacing="0em"><tspan x="61" y="54.6364">density = 2</tspan></text>
/// <text font-family="sans-serif" fill="#001AFF" style="white-space: pre" font-size="10" letter-spacing="0em"><tspan x="168" y="84.6364">density = 1</tspan></text>
/// <text font-family="sans-serif" fill="#14FF00" style="white-space: pre" font-size="10" letter-spacing="0em"><tspan x="174" y="121.636">density = 0.5</tspan></text>
/// <text font-family="sans-serif" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="161" y="190.864">distance</tspan></text>
/// <text font-family="sans-serif" transform="translate(10 132) rotate(-90)" fill="currentColor" style="white-space: pre" font-size="12" letter-spacing="0em"><tspan x="0" y="11.8636">fog intensity</tspan></text>
/// </svg>
ExponentialSquared { density: f32 },
coreh marked this conversation as resolved.
Show resolved Hide resolved
}

impl Default for Fog {
fn default() -> Self {
Fog {
color: Color::rgba(1.0, 1.0, 1.0, 1.0),
mode: FogMode::Linear {
start: 0.0,
end: 100.0,
},
}
}
}

impl ExtractComponent for Fog {
type Query = &'static Self;
type Filter = With<Camera>;

fn extract_component(item: QueryItem<Self::Query>) -> Self {
item.clone()
}
}
4 changes: 4 additions & 0 deletions crates/bevy_pbr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ pub mod wireframe;

mod alpha;
mod bundle;
mod fog;
mod light;
mod material;
mod pbr_material;
mod render;

pub use alpha::*;
pub use bundle::*;
pub use fog::*;
pub use light::*;
pub use material::*;
pub use pbr_material::*;
Expand All @@ -24,6 +26,7 @@ pub mod prelude {
DirectionalLightBundle, MaterialMeshBundle, PbrBundle, PointLightBundle,
SpotLightBundle,
},
fog::{Fog, FogMode},
light::{AmbientLight, DirectionalLight, PointLight, SpotLight},
material::{Material, MaterialPlugin},
pbr_material::StandardMaterial,
Expand Down Expand Up @@ -138,6 +141,7 @@ impl Plugin for PbrPlugin {
.init_resource::<DirectionalLightShadowMap>()
.init_resource::<PointLightShadowMap>()
.add_plugin(ExtractResourcePlugin::<AmbientLight>::default())
.add_plugin(FogPlugin)
.add_system_to_stage(
CoreStage::PostUpdate,
// NOTE: Clusters need to have been added before update_clusters is run so
Expand Down
8 changes: 8 additions & 0 deletions crates/bevy_pbr/src/pbr_material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ pub struct StandardMaterial {
/// shadows, alpha mode and ambient light are ignored if this is set to `true`.
pub unlit: bool,

/// Whether to disable fog for this material.
pub no_fog: bool,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we make this the positive version? i.e. fog_enabled

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can, I used a negative form mainly to make it consistent with unlit, and also because I thought maybe novice users would be confused with setting fog_enabled: true and not getting any fog.

BTW, do you think a per-entity setting would make sense, like NotShadowCaster, i.e. NotFogAffected instead of, or in addition to, a material flag?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think setting no_fog: false is more confusing. :)

A per-mesh entity flag could be good but it could be done in a follow up PR if you prefer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fog_enabled: true and not getting any fog.

Couldn't you just invert it were you are using it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it, it's now a positive rather than a negative flag. Yeah, I think I prefer to do the entity flag on a follow up PR, this branch/thread is already running quite long, it's getting somewhat hard to follow.


/// How to apply the alpha channel of the `base_color_texture`.
///
/// See [`AlphaMode`] for details. Defaults to [`AlphaMode::Opaque`].
Expand Down Expand Up @@ -254,6 +257,7 @@ impl Default for StandardMaterial {
double_sided: false,
cull_mode: Some(Face::Back),
unlit: false,
no_fog: false,
alpha_mode: AlphaMode::Opaque,
depth_bias: 0.0,
}
Expand Down Expand Up @@ -300,6 +304,7 @@ bitflags::bitflags! {
const ALPHA_MODE_BLEND = (1 << 8);
const TWO_COMPONENT_NORMAL_MAP = (1 << 9);
const FLIP_NORMAL_MAP_Y = (1 << 10);
const NO_FOG = (1 << 11);
const NONE = 0;
const UNINITIALIZED = 0xFFFF;
}
Expand Down Expand Up @@ -350,6 +355,9 @@ impl AsBindGroupShaderType<StandardMaterialUniform> for StandardMaterial {
if self.unlit {
flags |= StandardMaterialFlags::UNLIT;
}
if self.no_fog {
flags |= StandardMaterialFlags::NO_FOG;
}
let has_normal_map = self.normal_map_texture.is_some();
if has_normal_map {
if let Some(texture) = images.get(self.normal_map_texture.as_ref().unwrap()) {
Expand Down