diff --git a/crates/bevy_pbr/src/volumetric_fog/mod.rs b/crates/bevy_pbr/src/volumetric_fog/mod.rs index ddc9b976c9e63..82aedd3d0b277 100644 --- a/crates/bevy_pbr/src/volumetric_fog/mod.rs +++ b/crates/bevy_pbr/src/volumetric_fog/mod.rs @@ -153,11 +153,11 @@ pub struct FogVolume { /// Optional 3D voxel density texture for the fog. pub density_texture: Option>, - /// Configurable offset of the density texture in UVW coordinates. Values 1.0 or higher - /// will be wrapped into the (0.0..1.0) range. + /// Configurable offset of the density texture in UVW coordinates. /// /// This can be used to scroll a repeating density texture in a direction over time - /// to create effects like fog moving in the wind. + /// to create effects like fog moving in the wind. Make sure to configure the texture + /// to use `ImageAddressMode::Repeat` if this is your intention. /// /// Has no effect when no density texture is present. /// diff --git a/crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl b/crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl index 68e929103275f..2c30eddbeaf8b 100644 --- a/crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl +++ b/crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl @@ -238,11 +238,7 @@ fn fragment(@builtin(position) position: vec4) -> @location(0) vec4 { // case. let P_uvw = Ro_uvw + Rd_step_uvw * f32(step); if (all(P_uvw >= vec3(0.0)) && all(P_uvw <= vec3(1.0))) { - // Add density texture offset and wrap values exceeding the (0, 0, 0) to (1, 1, 1) range. - var uvw = P_uvw + density_texture_offset; - uvw -= floor(uvw); - - density *= textureSample(density_texture, density_sampler, uvw).r; + density *= textureSample(density_texture, density_sampler, P_uvw + density_texture_offset).r; } else { density = 0.0; } diff --git a/examples/3d/scrolling_fog.rs b/examples/3d/scrolling_fog.rs index cfec3b255d78f..1813f99920bcd 100644 --- a/examples/3d/scrolling_fog.rs +++ b/examples/3d/scrolling_fog.rs @@ -14,6 +14,9 @@ use bevy::core_pipeline::bloom::BloomSettings; use bevy::core_pipeline::experimental::taa::{TemporalAntiAliasBundle, TemporalAntiAliasPlugin}; use bevy::pbr::{DirectionalLightShadowMap, FogVolume, VolumetricFogSettings, VolumetricLight}; use bevy::prelude::*; +use bevy_render::texture::{ + ImageAddressMode, ImageFilterMode, ImageLoaderSettings, ImageSampler, ImageSamplerDescriptor, +}; /// Initializes the example. fn main() { @@ -94,7 +97,25 @@ fn setup( ..default() }); - // Spawn FogVolume with repeating 3d noise density texture. + // Load a repeating 3d noise texture. Make sure to set ImageAddressMode to Repeat + // so that the texture wraps around as the density texture offset is moved along. + // Also set ImageFilterMode to Linear so that the fog isn't pixelated. + let noise_texture = assets.load_with_settings("volumes/fog_noise.ktx2", |settings: &mut _| { + *settings = ImageLoaderSettings { + sampler: ImageSampler::Descriptor(ImageSamplerDescriptor { + address_mode_u: ImageAddressMode::Repeat, + address_mode_v: ImageAddressMode::Repeat, + address_mode_w: ImageAddressMode::Repeat, + mag_filter: ImageFilterMode::Linear, + min_filter: ImageFilterMode::Linear, + mipmap_filter: ImageFilterMode::Linear, + ..default() + }), + ..default() + } + }); + + // Spawn a FogVolume and use the repeating noise texture as its density texture. commands.spawn(( SpatialBundle { visibility: Visibility::Visible, @@ -102,7 +123,7 @@ fn setup( ..default() }, FogVolume { - density_texture: Some(assets.load("volumes/fog_noise.ktx2")), + density_texture: Some(noise_texture), density_factor: 0.05, ..default() },