use bevy::prelude::*;
use bevy::render::diagnostic::RecordDiagnostics;
use bevy::render::extract_component::{ComponentUniforms, DynamicUniformIndex};
use bevy::render::render_graph::{NodeRunError, RenderGraphContext, ViewNode};
use bevy::render::render_resource::{
BindGroupEntries, Operations, PipelineCache, RenderPassColorAttachment, RenderPassDescriptor,
};
use bevy::render::renderer::RenderContext;
use bevy::render::view::{Msaa, ViewDepthTexture, ViewTarget, ViewUniformOffset, ViewUniforms};
use crate::component::ExponentialHeightFogUniform;
use crate::pipeline::{ExponentialHeightFogPipeline, ExponentialHeightFogPipelineId};
#[derive(Default)]
pub struct ExponentialHeightFogNode;
impl ViewNode for ExponentialHeightFogNode {
type ViewQuery = (
&'static ViewTarget,
&'static ViewDepthTexture,
&'static ExponentialHeightFogPipelineId,
&'static ViewUniformOffset,
&'static DynamicUniformIndex<ExponentialHeightFogUniform>,
&'static Msaa,
);
fn run(
&self,
_graph: &mut RenderGraphContext,
render_context: &mut RenderContext,
(
view_target,
view_depth_texture,
pipeline_id,
view_uniform_offset,
fog_uniform_index,
msaa,
): bevy::ecs::query::QueryItem<'_, '_, Self::ViewQuery>,
world: &World,
) -> Result<(), NodeRunError> {
let pipeline_cache = world.resource::<PipelineCache>();
let fog_pipeline = world.resource::<ExponentialHeightFogPipeline>();
let view_uniforms = world.resource::<ViewUniforms>();
let fog_uniforms = world.resource::<ComponentUniforms<ExponentialHeightFogUniform>>();
let Some(pipeline) = pipeline_cache.get_render_pipeline(pipeline_id.0) else {
return Ok(());
};
let Some(view_uniforms_binding) = view_uniforms.uniforms.binding() else {
return Ok(());
};
let Some(fog_uniforms_binding) = fog_uniforms.uniforms().binding() else {
return Ok(());
};
let diagnostics = render_context.diagnostic_recorder();
let post_process = view_target.post_process_write();
let bind_group_layout = if msaa.samples() > 1 {
&fog_pipeline.layout_msaa
} else {
&fog_pipeline.layout
};
let bind_group = render_context.render_device().create_bind_group(
Some("exponential_height_fog_bind_group"),
&pipeline_cache.get_bind_group_layout(bind_group_layout),
&BindGroupEntries::sequential((
view_uniforms_binding,
view_depth_texture.view(),
post_process.source,
&fog_pipeline.sampler,
fog_uniforms_binding,
)),
);
let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
label: Some("exponential_height_fog"),
color_attachments: &[Some(RenderPassColorAttachment {
view: post_process.destination,
depth_slice: None,
resolve_target: None,
ops: Operations::default(),
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
});
let pass_span = diagnostics.pass_span(&mut render_pass, "exponential_height_fog");
render_pass.set_render_pipeline(pipeline);
render_pass.set_bind_group(
0,
&bind_group,
&[view_uniform_offset.offset, fog_uniform_index.index()],
);
render_pass.draw(0..3, 0..1);
pass_span.end(&mut render_pass);
Ok(())
}
}