Path: blob/main/crates/bevy_pbr/src/atmosphere/resources.rs
9418 views
use crate::{1ExtractedAtmosphere, GpuLights, GpuScatteringMedium, LightMeta, ScatteringMediumSampler,2};3use bevy_asset::{load_embedded_asset, AssetId, Handle};4use bevy_camera::{Camera, Camera3d};5use bevy_core_pipeline::FullscreenShader;6use bevy_derive::Deref;7use bevy_ecs::{8component::Component,9entity::Entity,10error::BevyError,11query::With,12resource::Resource,13system::{Commands, Query, Res, ResMut},14world::{FromWorld, World},15};16use bevy_image::ToExtents;17use bevy_light::atmosphere::ScatteringMedium;18use bevy_math::{Affine3A, Mat4, Vec3, Vec3A};19use bevy_render::{20extract_component::ComponentUniforms,21render_asset::RenderAssets,22render_resource::{binding_types::*, *},23renderer::{RenderDevice, RenderQueue},24texture::{CachedTexture, TextureCache},25view::{ExtractedView, Msaa, ViewDepthTexture, ViewUniform, ViewUniforms},26};27use bevy_shader::Shader;28use bevy_utils::default;2930use super::GpuAtmosphereSettings;3132#[derive(Resource)]33pub(crate) struct AtmosphereBindGroupLayouts {34pub transmittance_lut: BindGroupLayoutDescriptor,35pub multiscattering_lut: BindGroupLayoutDescriptor,36pub sky_view_lut: BindGroupLayoutDescriptor,37pub aerial_view_lut: BindGroupLayoutDescriptor,38}3940#[derive(Resource)]41pub(crate) struct RenderSkyBindGroupLayouts {42pub render_sky: BindGroupLayoutDescriptor,43pub render_sky_msaa: BindGroupLayoutDescriptor,44pub fullscreen_shader: FullscreenShader,45pub fragment_shader: Handle<Shader>,46}4748impl AtmosphereBindGroupLayouts {49pub fn new() -> Self {50let transmittance_lut = BindGroupLayoutDescriptor::new(51"transmittance_lut_bind_group_layout",52&BindGroupLayoutEntries::with_indices(53ShaderStages::COMPUTE,54(55(0, uniform_buffer::<GpuAtmosphere>(true)),56(1, uniform_buffer::<GpuAtmosphereSettings>(true)),57// scattering medium luts and sampler58(5, texture_2d(TextureSampleType::default())),59(6, texture_2d(TextureSampleType::default())),60(7, sampler(SamplerBindingType::Filtering)),61// transmittance lut storage texture62(6313,64texture_storage_2d(65TextureFormat::Rgba16Float,66StorageTextureAccess::WriteOnly,67),68),69),70),71);7273let multiscattering_lut = BindGroupLayoutDescriptor::new(74"multiscattering_lut_bind_group_layout",75&BindGroupLayoutEntries::with_indices(76ShaderStages::COMPUTE,77(78(0, uniform_buffer::<GpuAtmosphere>(true)),79(1, uniform_buffer::<GpuAtmosphereSettings>(true)),80// scattering medium luts and sampler81(5, texture_2d(TextureSampleType::default())),82(6, texture_2d(TextureSampleType::default())),83(7, sampler(SamplerBindingType::Filtering)),84// atmosphere luts and sampler85(8, texture_2d(TextureSampleType::default())), // transmittance86(12, sampler(SamplerBindingType::Filtering)),87// multiscattering lut storage texture88(8913,90texture_storage_2d(91TextureFormat::Rgba16Float,92StorageTextureAccess::WriteOnly,93),94),95),96),97);9899let sky_view_lut = BindGroupLayoutDescriptor::new(100"sky_view_lut_bind_group_layout",101&BindGroupLayoutEntries::with_indices(102ShaderStages::COMPUTE,103(104(0, uniform_buffer::<GpuAtmosphere>(true)),105(1, uniform_buffer::<GpuAtmosphereSettings>(true)),106(2, uniform_buffer::<AtmosphereTransform>(true)),107(3, uniform_buffer::<ViewUniform>(true)),108(4, uniform_buffer::<GpuLights>(true)),109// scattering medium luts and sampler110(5, texture_2d(TextureSampleType::default())),111(6, texture_2d(TextureSampleType::default())),112(7, sampler(SamplerBindingType::Filtering)),113// atmosphere luts and sampler114(8, texture_2d(TextureSampleType::default())), // transmittance115(9, texture_2d(TextureSampleType::default())), // multiscattering116(12, sampler(SamplerBindingType::Filtering)),117// sky view lut storage texture118(11913,120texture_storage_2d(121TextureFormat::Rgba16Float,122StorageTextureAccess::WriteOnly,123),124),125),126),127);128129let aerial_view_lut = BindGroupLayoutDescriptor::new(130"aerial_view_lut_bind_group_layout",131&BindGroupLayoutEntries::with_indices(132ShaderStages::COMPUTE,133(134(0, uniform_buffer::<GpuAtmosphere>(true)),135(1, uniform_buffer::<GpuAtmosphereSettings>(true)),136(3, uniform_buffer::<ViewUniform>(true)),137(4, uniform_buffer::<GpuLights>(true)),138// scattering medium luts and sampler139(5, texture_2d(TextureSampleType::default())),140(6, texture_2d(TextureSampleType::default())),141(7, sampler(SamplerBindingType::Filtering)),142// atmosphere luts and sampler143(8, texture_2d(TextureSampleType::default())), // transmittance144(9, texture_2d(TextureSampleType::default())), // multiscattering145(12, sampler(SamplerBindingType::Filtering)),146// eerial view lut storage texture147(14813,149texture_storage_3d(150TextureFormat::Rgba16Float,151StorageTextureAccess::WriteOnly,152),153),154),155),156);157158Self {159transmittance_lut,160multiscattering_lut,161sky_view_lut,162aerial_view_lut,163}164}165}166167impl FromWorld for RenderSkyBindGroupLayouts {168fn from_world(world: &mut World) -> Self {169let render_sky = BindGroupLayoutDescriptor::new(170"render_sky_bind_group_layout",171&BindGroupLayoutEntries::with_indices(172ShaderStages::FRAGMENT,173(174(0, uniform_buffer::<GpuAtmosphere>(true)),175(1, uniform_buffer::<GpuAtmosphereSettings>(true)),176(2, uniform_buffer::<AtmosphereTransform>(true)),177(3, uniform_buffer::<ViewUniform>(true)),178(4, uniform_buffer::<GpuLights>(true)),179// scattering medium luts and sampler180(5, texture_2d(TextureSampleType::default())),181(6, texture_2d(TextureSampleType::default())),182(7, sampler(SamplerBindingType::Filtering)),183// atmosphere luts and sampler184(8, texture_2d(TextureSampleType::default())), // transmittance185(9, texture_2d(TextureSampleType::default())), // multiscattering186(10, texture_2d(TextureSampleType::default())), // sky view187(11, texture_3d(TextureSampleType::default())), // aerial view188(12, sampler(SamplerBindingType::Filtering)),189// view depth texture190(13, texture_2d(TextureSampleType::Depth)),191),192),193);194195let render_sky_msaa = BindGroupLayoutDescriptor::new(196"render_sky_msaa_bind_group_layout",197&BindGroupLayoutEntries::with_indices(198ShaderStages::FRAGMENT,199(200(0, uniform_buffer::<GpuAtmosphere>(true)),201(1, uniform_buffer::<GpuAtmosphereSettings>(true)),202(2, uniform_buffer::<AtmosphereTransform>(true)),203(3, uniform_buffer::<ViewUniform>(true)),204(4, uniform_buffer::<GpuLights>(true)),205// scattering medium luts and sampler206(5, texture_2d(TextureSampleType::default())),207(6, texture_2d(TextureSampleType::default())),208(7, sampler(SamplerBindingType::Filtering)),209// atmosphere luts and sampler210(8, texture_2d(TextureSampleType::default())), // transmittance211(9, texture_2d(TextureSampleType::default())), // multiscattering212(10, texture_2d(TextureSampleType::default())), // sky view213(11, texture_3d(TextureSampleType::default())), // aerial view214(12, sampler(SamplerBindingType::Filtering)),215// view depth texture216(13, texture_2d_multisampled(TextureSampleType::Depth)),217),218),219);220221Self {222render_sky,223render_sky_msaa,224fullscreen_shader: world.resource::<FullscreenShader>().clone(),225fragment_shader: load_embedded_asset!(world, "render_sky.wgsl"),226}227}228}229230#[derive(Resource, Deref)]231pub struct AtmosphereSampler(Sampler);232233impl FromWorld for AtmosphereSampler {234fn from_world(world: &mut World) -> Self {235let render_device = world.resource::<RenderDevice>();236237let sampler = render_device.create_sampler(&SamplerDescriptor {238mag_filter: FilterMode::Linear,239min_filter: FilterMode::Linear,240mipmap_filter: MipmapFilterMode::Nearest,241..Default::default()242});243244Self(sampler)245}246}247248#[derive(Resource)]249pub(crate) struct AtmosphereLutPipelines {250pub transmittance_lut: CachedComputePipelineId,251pub multiscattering_lut: CachedComputePipelineId,252pub sky_view_lut: CachedComputePipelineId,253pub aerial_view_lut: CachedComputePipelineId,254}255256impl FromWorld for AtmosphereLutPipelines {257fn from_world(world: &mut World) -> Self {258let pipeline_cache = world.resource::<PipelineCache>();259let layouts = world.resource::<AtmosphereBindGroupLayouts>();260261let transmittance_lut = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {262label: Some("transmittance_lut_pipeline".into()),263layout: vec![layouts.transmittance_lut.clone()],264shader: load_embedded_asset!(world, "transmittance_lut.wgsl"),265..default()266});267268let multiscattering_lut =269pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {270label: Some("multi_scattering_lut_pipeline".into()),271layout: vec![layouts.multiscattering_lut.clone()],272shader: load_embedded_asset!(world, "multiscattering_lut.wgsl"),273..default()274});275276let sky_view_lut = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {277label: Some("sky_view_lut_pipeline".into()),278layout: vec![layouts.sky_view_lut.clone()],279shader: load_embedded_asset!(world, "sky_view_lut.wgsl"),280..default()281});282283let aerial_view_lut = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {284label: Some("aerial_view_lut_pipeline".into()),285layout: vec![layouts.aerial_view_lut.clone()],286shader: load_embedded_asset!(world, "aerial_view_lut.wgsl"),287..default()288});289290Self {291transmittance_lut,292multiscattering_lut,293sky_view_lut,294aerial_view_lut,295}296}297}298299#[derive(Component)]300pub(crate) struct RenderSkyPipelineId(pub CachedRenderPipelineId);301302#[derive(Copy, Clone, Hash, PartialEq, Eq)]303pub(crate) struct RenderSkyPipelineKey {304pub msaa_samples: u32,305pub dual_source_blending: bool,306}307308impl SpecializedRenderPipeline for RenderSkyBindGroupLayouts {309type Key = RenderSkyPipelineKey;310311fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {312let mut shader_defs = Vec::new();313314if key.msaa_samples > 1 {315shader_defs.push("MULTISAMPLED".into());316}317if key.dual_source_blending {318shader_defs.push("DUAL_SOURCE_BLENDING".into());319}320321let dst_factor = if key.dual_source_blending {322BlendFactor::Src1323} else {324BlendFactor::SrcAlpha325};326327RenderPipelineDescriptor {328label: Some(format!("render_sky_pipeline_{}", key.msaa_samples).into()),329layout: vec![if key.msaa_samples == 1 {330self.render_sky.clone()331} else {332self.render_sky_msaa.clone()333}],334vertex: self.fullscreen_shader.to_vertex_state(),335fragment: Some(FragmentState {336shader: self.fragment_shader.clone(),337shader_defs,338targets: vec![Some(ColorTargetState {339format: TextureFormat::Rgba16Float,340blend: Some(BlendState {341color: BlendComponent {342src_factor: BlendFactor::One,343dst_factor,344operation: BlendOperation::Add,345},346alpha: BlendComponent {347src_factor: BlendFactor::Zero,348dst_factor: BlendFactor::One,349operation: BlendOperation::Add,350},351}),352write_mask: ColorWrites::ALL,353})],354..default()355}),356multisample: MultisampleState {357count: key.msaa_samples,358..default()359},360..default()361}362}363}364365pub(super) fn queue_render_sky_pipelines(366views: Query<(Entity, &Msaa), (With<Camera>, With<ExtractedAtmosphere>)>,367pipeline_cache: Res<PipelineCache>,368layouts: Res<RenderSkyBindGroupLayouts>,369mut specializer: ResMut<SpecializedRenderPipelines<RenderSkyBindGroupLayouts>>,370render_device: Res<RenderDevice>,371mut commands: Commands,372) {373for (entity, msaa) in &views {374let id = specializer.specialize(375&pipeline_cache,376&layouts,377RenderSkyPipelineKey {378msaa_samples: msaa.samples(),379dual_source_blending: render_device380.features()381.contains(WgpuFeatures::DUAL_SOURCE_BLENDING),382},383);384commands.entity(entity).insert(RenderSkyPipelineId(id));385}386}387388#[derive(Component)]389pub struct AtmosphereTextures {390pub transmittance_lut: CachedTexture,391pub multiscattering_lut: CachedTexture,392pub sky_view_lut: CachedTexture,393pub aerial_view_lut: CachedTexture,394}395396pub(super) fn prepare_atmosphere_textures(397views: Query<(Entity, &GpuAtmosphereSettings), With<ExtractedAtmosphere>>,398render_device: Res<RenderDevice>,399mut texture_cache: ResMut<TextureCache>,400mut commands: Commands,401) {402for (entity, lut_settings) in &views {403let transmittance_lut = texture_cache.get(404&render_device,405TextureDescriptor {406label: Some("transmittance_lut"),407size: lut_settings.transmittance_lut_size.to_extents(),408mip_level_count: 1,409sample_count: 1,410dimension: TextureDimension::D2,411format: TextureFormat::Rgba16Float,412usage: TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING,413view_formats: &[],414},415);416417let multiscattering_lut = texture_cache.get(418&render_device,419TextureDescriptor {420label: Some("multiscattering_lut"),421size: lut_settings.multiscattering_lut_size.to_extents(),422mip_level_count: 1,423sample_count: 1,424dimension: TextureDimension::D2,425format: TextureFormat::Rgba16Float,426usage: TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING,427view_formats: &[],428},429);430431let sky_view_lut = texture_cache.get(432&render_device,433TextureDescriptor {434label: Some("sky_view_lut"),435size: lut_settings.sky_view_lut_size.to_extents(),436mip_level_count: 1,437sample_count: 1,438dimension: TextureDimension::D2,439format: TextureFormat::Rgba16Float,440usage: TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING,441view_formats: &[],442},443);444445let aerial_view_lut = texture_cache.get(446&render_device,447TextureDescriptor {448label: Some("aerial_view_lut"),449size: lut_settings.aerial_view_lut_size.to_extents(),450mip_level_count: 1,451sample_count: 1,452dimension: TextureDimension::D3,453format: TextureFormat::Rgba16Float,454usage: TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING,455view_formats: &[],456},457);458459commands.entity(entity).insert({460AtmosphereTextures {461transmittance_lut,462multiscattering_lut,463sky_view_lut,464aerial_view_lut,465}466});467}468}469470#[derive(Copy, Clone, Debug, thiserror::Error)]471#[error("ScatteringMedium missing with id {0:?}: make sure the asset was not removed.")]472struct ScatteringMediumMissingError(AssetId<ScatteringMedium>);473474/// The shader-uniform representation of an Atmosphere.475#[derive(Clone, Component, ShaderType)]476pub struct GpuAtmosphere {477//TODO: rename to Planet later?478pub ground_albedo: Vec3,479pub bottom_radius: f32,480pub top_radius: f32,481}482483pub fn prepare_atmosphere_uniforms(484mut commands: Commands,485atmospheres: Query<(Entity, &ExtractedAtmosphere)>,486) -> Result<(), BevyError> {487for (entity, atmosphere) in atmospheres {488commands.entity(entity).insert(GpuAtmosphere {489ground_albedo: atmosphere.ground_albedo,490bottom_radius: atmosphere.bottom_radius,491top_radius: atmosphere.top_radius,492});493}494Ok(())495}496497#[derive(Resource, Default)]498pub struct AtmosphereTransforms {499uniforms: DynamicUniformBuffer<AtmosphereTransform>,500}501502impl AtmosphereTransforms {503#[inline]504pub fn uniforms(&self) -> &DynamicUniformBuffer<AtmosphereTransform> {505&self.uniforms506}507}508509#[derive(ShaderType)]510pub struct AtmosphereTransform {511world_from_atmosphere: Mat4,512}513514#[derive(Component)]515pub struct AtmosphereTransformsOffset {516index: u32,517}518519impl AtmosphereTransformsOffset {520#[inline]521pub fn index(&self) -> u32 {522self.index523}524}525526pub(super) fn prepare_atmosphere_transforms(527views: Query<(Entity, &ExtractedView), (With<ExtractedAtmosphere>, With<Camera3d>)>,528render_device: Res<RenderDevice>,529render_queue: Res<RenderQueue>,530mut atmo_uniforms: ResMut<AtmosphereTransforms>,531mut commands: Commands,532) {533let atmo_count = views.iter().len();534let Some(mut writer) =535atmo_uniforms536.uniforms537.get_writer(atmo_count, &render_device, &render_queue)538else {539return;540};541542for (entity, view) in &views {543let world_from_view = view.world_from_view.affine();544let camera_z = world_from_view.matrix3.z_axis;545let camera_y = world_from_view.matrix3.y_axis;546let atmo_z = camera_z547.with_y(0.0)548.try_normalize()549.unwrap_or_else(|| camera_y.with_y(0.0).normalize());550let atmo_y = Vec3A::Y;551let atmo_x = atmo_y.cross(atmo_z).normalize();552let world_from_atmosphere =553Affine3A::from_cols(atmo_x, atmo_y, atmo_z, world_from_view.translation);554555let world_from_atmosphere = Mat4::from(world_from_atmosphere);556557commands.entity(entity).insert(AtmosphereTransformsOffset {558index: writer.write(&AtmosphereTransform {559world_from_atmosphere,560}),561});562}563}564565#[derive(Component)]566pub(crate) struct AtmosphereBindGroups {567pub transmittance_lut: BindGroup,568pub multiscattering_lut: BindGroup,569pub sky_view_lut: BindGroup,570pub aerial_view_lut: BindGroup,571pub render_sky: BindGroup,572}573574#[derive(Copy, Clone, Debug, thiserror::Error)]575enum AtmosphereBindGroupError {576#[error("Failed to prepare atmosphere bind groups. Atmosphere uniform buffer missing")]577Atmosphere,578#[error(579"Failed to prepare atmosphere bind groups. AtmosphereTransforms uniform buffer missing"580)]581Transforms,582#[error("Failed to prepare atmosphere bind groups. AtmosphereSettings uniform buffer missing")]583Settings,584#[error("Failed to prepare atmosphere bind groups. View uniform buffer missing")]585ViewUniforms,586#[error("Failed to prepare atmosphere bind groups. Light uniform buffer missing")]587LightUniforms,588}589590pub(super) fn prepare_atmosphere_bind_groups(591views: Query<592(593Entity,594&ExtractedAtmosphere,595&AtmosphereTextures,596&ViewDepthTexture,597&Msaa,598),599(With<Camera3d>, With<ExtractedAtmosphere>),600>,601render_device: Res<RenderDevice>,602layouts: Res<AtmosphereBindGroupLayouts>,603render_sky_layouts: Res<RenderSkyBindGroupLayouts>,604atmosphere_sampler: Res<AtmosphereSampler>,605view_uniforms: Res<ViewUniforms>,606lights_uniforms: Res<LightMeta>,607atmosphere_transforms: Res<AtmosphereTransforms>,608atmosphere_uniforms: Res<ComponentUniforms<GpuAtmosphere>>,609settings_uniforms: Res<ComponentUniforms<GpuAtmosphereSettings>>,610gpu_media: Res<RenderAssets<GpuScatteringMedium>>,611medium_sampler: Res<ScatteringMediumSampler>,612pipeline_cache: Res<PipelineCache>,613mut commands: Commands,614) -> Result<(), BevyError> {615if views.iter().len() == 0 {616return Ok(());617}618619let atmosphere_binding = atmosphere_uniforms620.binding()621.ok_or(AtmosphereBindGroupError::Atmosphere)?;622623let transforms_binding = atmosphere_transforms624.uniforms()625.binding()626.ok_or(AtmosphereBindGroupError::Transforms)?;627628let settings_binding = settings_uniforms629.binding()630.ok_or(AtmosphereBindGroupError::Settings)?;631632let view_binding = view_uniforms633.uniforms634.binding()635.ok_or(AtmosphereBindGroupError::ViewUniforms)?;636637let lights_binding = lights_uniforms638.view_gpu_lights639.binding()640.ok_or(AtmosphereBindGroupError::LightUniforms)?;641642for (entity, atmosphere, textures, view_depth_texture, msaa) in &views {643let gpu_medium = gpu_media644.get(atmosphere.medium)645.ok_or(ScatteringMediumMissingError(atmosphere.medium))?;646647let transmittance_lut = render_device.create_bind_group(648"transmittance_lut_bind_group",649&pipeline_cache.get_bind_group_layout(&layouts.transmittance_lut),650&BindGroupEntries::with_indices((651// uniforms652(0, atmosphere_binding.clone()),653(1, settings_binding.clone()),654// scattering medium luts and sampler655(5, &gpu_medium.density_lut_view),656(6, &gpu_medium.scattering_lut_view),657(7, medium_sampler.sampler()),658// transmittance lut storage texture659(13, &textures.transmittance_lut.default_view),660)),661);662663let multiscattering_lut = render_device.create_bind_group(664"multiscattering_lut_bind_group",665&pipeline_cache.get_bind_group_layout(&layouts.multiscattering_lut),666&BindGroupEntries::with_indices((667// uniforms668(0, atmosphere_binding.clone()),669(1, settings_binding.clone()),670// scattering medium luts and sampler671(5, &gpu_medium.density_lut_view),672(6, &gpu_medium.scattering_lut_view),673(7, medium_sampler.sampler()),674// atmosphere luts and sampler675(8, &textures.transmittance_lut.default_view),676(12, &**atmosphere_sampler),677// multiscattering lut storage texture678(13, &textures.multiscattering_lut.default_view),679)),680);681682let sky_view_lut = render_device.create_bind_group(683"sky_view_lut_bind_group",684&pipeline_cache.get_bind_group_layout(&layouts.sky_view_lut),685&BindGroupEntries::with_indices((686// uniforms687(0, atmosphere_binding.clone()),688(1, settings_binding.clone()),689(2, transforms_binding.clone()),690(3, view_binding.clone()),691(4, lights_binding.clone()),692// scattering medium luts and sampler693(5, &gpu_medium.density_lut_view),694(6, &gpu_medium.scattering_lut_view),695(7, medium_sampler.sampler()),696// atmosphere luts and sampler697(8, &textures.transmittance_lut.default_view),698(9, &textures.multiscattering_lut.default_view),699(12, &**atmosphere_sampler),700// sky view lut storage texture701(13, &textures.sky_view_lut.default_view),702)),703);704705let aerial_view_lut = render_device.create_bind_group(706"sky_view_lut_bind_group",707&pipeline_cache.get_bind_group_layout(&layouts.aerial_view_lut),708&BindGroupEntries::with_indices((709// uniforms710(0, atmosphere_binding.clone()),711(1, settings_binding.clone()),712(3, view_binding.clone()),713(4, lights_binding.clone()),714// scattering medium luts and sampler715(5, &gpu_medium.density_lut_view),716(6, &gpu_medium.scattering_lut_view),717(7, medium_sampler.sampler()),718// atmosphere luts and sampler719(8, &textures.transmittance_lut.default_view),720(9, &textures.multiscattering_lut.default_view),721(12, &**atmosphere_sampler),722// aerial view lut storage texture723(13, &textures.aerial_view_lut.default_view),724)),725);726727let render_sky = render_device.create_bind_group(728"render_sky_bind_group",729&pipeline_cache.get_bind_group_layout(if *msaa == Msaa::Off {730&render_sky_layouts.render_sky731} else {732&render_sky_layouts.render_sky_msaa733}),734&BindGroupEntries::with_indices((735// uniforms736(0, atmosphere_binding.clone()),737(1, settings_binding.clone()),738(2, transforms_binding.clone()),739(3, view_binding.clone()),740(4, lights_binding.clone()),741// scattering medium luts and sampler742(5, &gpu_medium.density_lut_view),743(6, &gpu_medium.scattering_lut_view),744(7, medium_sampler.sampler()),745// atmosphere luts and sampler746(8, &textures.transmittance_lut.default_view),747(9, &textures.multiscattering_lut.default_view),748(10, &textures.sky_view_lut.default_view),749(11, &textures.aerial_view_lut.default_view),750(12, &**atmosphere_sampler),751// view depth texture752(13, view_depth_texture.view()),753)),754);755756commands.entity(entity).insert(AtmosphereBindGroups {757transmittance_lut,758multiscattering_lut,759sky_view_lut,760aerial_view_lut,761render_sky,762});763}764765Ok(())766}767768#[derive(ShaderType)]769#[repr(C)]770pub(crate) struct AtmosphereData {771pub atmosphere: GpuAtmosphere,772pub settings: GpuAtmosphereSettings,773}774775pub fn init_atmosphere_buffer(mut commands: Commands) {776commands.insert_resource(AtmosphereBuffer {777buffer: StorageBuffer::from(AtmosphereData {778atmosphere: GpuAtmosphere {779ground_albedo: Vec3::ZERO,780bottom_radius: 0.0,781top_radius: 0.0,782},783settings: GpuAtmosphereSettings::default(),784}),785});786}787788#[derive(Resource)]789pub struct AtmosphereBuffer {790pub(crate) buffer: StorageBuffer<AtmosphereData>,791}792793pub(crate) fn write_atmosphere_buffer(794device: Res<RenderDevice>,795queue: Res<RenderQueue>,796atmosphere_entity: Query<(&GpuAtmosphere, &GpuAtmosphereSettings), With<Camera3d>>,797mut atmosphere_buffer: ResMut<AtmosphereBuffer>,798) {799let Ok((atmosphere, settings)) = atmosphere_entity.single() else {800return;801};802803atmosphere_buffer.buffer.set(AtmosphereData {804atmosphere: atmosphere.clone(),805settings: settings.clone(),806});807atmosphere_buffer.buffer.write_buffer(&device, &queue);808}809810811