Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_pbr/src/atmosphere/node.rs
6604 views
1
use bevy_ecs::{query::QueryItem, system::lifetimeless::Read, world::World};
2
use bevy_math::{UVec2, Vec3Swizzles};
3
use bevy_render::{
4
diagnostic::RecordDiagnostics,
5
extract_component::DynamicUniformIndex,
6
render_graph::{NodeRunError, RenderGraphContext, RenderLabel, ViewNode},
7
render_resource::{ComputePass, ComputePassDescriptor, PipelineCache, RenderPassDescriptor},
8
renderer::RenderContext,
9
view::{ViewTarget, ViewUniformOffset},
10
};
11
12
use crate::ViewLightsUniformOffset;
13
14
use super::{
15
resources::{
16
AtmosphereBindGroups, AtmosphereLutPipelines, AtmosphereTransformsOffset,
17
RenderSkyPipelineId,
18
},
19
Atmosphere, GpuAtmosphereSettings,
20
};
21
22
#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash, RenderLabel)]
23
pub enum AtmosphereNode {
24
RenderLuts,
25
RenderSky,
26
Environment,
27
}
28
29
#[derive(Default)]
30
pub(super) struct AtmosphereLutsNode {}
31
32
impl ViewNode for AtmosphereLutsNode {
33
type ViewQuery = (
34
Read<GpuAtmosphereSettings>,
35
Read<AtmosphereBindGroups>,
36
Read<DynamicUniformIndex<Atmosphere>>,
37
Read<DynamicUniformIndex<GpuAtmosphereSettings>>,
38
Read<AtmosphereTransformsOffset>,
39
Read<ViewUniformOffset>,
40
Read<ViewLightsUniformOffset>,
41
);
42
43
fn run(
44
&self,
45
_graph: &mut RenderGraphContext,
46
render_context: &mut RenderContext,
47
(
48
settings,
49
bind_groups,
50
atmosphere_uniforms_offset,
51
settings_uniforms_offset,
52
atmosphere_transforms_offset,
53
view_uniforms_offset,
54
lights_uniforms_offset,
55
): QueryItem<Self::ViewQuery>,
56
world: &World,
57
) -> Result<(), NodeRunError> {
58
let pipelines = world.resource::<AtmosphereLutPipelines>();
59
let pipeline_cache = world.resource::<PipelineCache>();
60
let (
61
Some(transmittance_lut_pipeline),
62
Some(multiscattering_lut_pipeline),
63
Some(sky_view_lut_pipeline),
64
Some(aerial_view_lut_pipeline),
65
) = (
66
pipeline_cache.get_compute_pipeline(pipelines.transmittance_lut),
67
pipeline_cache.get_compute_pipeline(pipelines.multiscattering_lut),
68
pipeline_cache.get_compute_pipeline(pipelines.sky_view_lut),
69
pipeline_cache.get_compute_pipeline(pipelines.aerial_view_lut),
70
)
71
else {
72
return Ok(());
73
};
74
75
let diagnostics = render_context.diagnostic_recorder();
76
77
let command_encoder = render_context.command_encoder();
78
79
let mut luts_pass = command_encoder.begin_compute_pass(&ComputePassDescriptor {
80
label: Some("atmosphere_luts"),
81
timestamp_writes: None,
82
});
83
let pass_span = diagnostics.time_span(&mut luts_pass, "atmosphere_luts");
84
85
fn dispatch_2d(compute_pass: &mut ComputePass, size: UVec2) {
86
const WORKGROUP_SIZE: u32 = 16;
87
let workgroups_x = size.x.div_ceil(WORKGROUP_SIZE);
88
let workgroups_y = size.y.div_ceil(WORKGROUP_SIZE);
89
compute_pass.dispatch_workgroups(workgroups_x, workgroups_y, 1);
90
}
91
92
// Transmittance LUT
93
94
luts_pass.set_pipeline(transmittance_lut_pipeline);
95
luts_pass.set_bind_group(
96
0,
97
&bind_groups.transmittance_lut,
98
&[
99
atmosphere_uniforms_offset.index(),
100
settings_uniforms_offset.index(),
101
],
102
);
103
104
dispatch_2d(&mut luts_pass, settings.transmittance_lut_size);
105
106
// Multiscattering LUT
107
108
luts_pass.set_pipeline(multiscattering_lut_pipeline);
109
luts_pass.set_bind_group(
110
0,
111
&bind_groups.multiscattering_lut,
112
&[
113
atmosphere_uniforms_offset.index(),
114
settings_uniforms_offset.index(),
115
],
116
);
117
118
luts_pass.dispatch_workgroups(
119
settings.multiscattering_lut_size.x,
120
settings.multiscattering_lut_size.y,
121
1,
122
);
123
124
// Sky View LUT
125
126
luts_pass.set_pipeline(sky_view_lut_pipeline);
127
luts_pass.set_bind_group(
128
0,
129
&bind_groups.sky_view_lut,
130
&[
131
atmosphere_uniforms_offset.index(),
132
settings_uniforms_offset.index(),
133
atmosphere_transforms_offset.index(),
134
view_uniforms_offset.offset,
135
lights_uniforms_offset.offset,
136
],
137
);
138
139
dispatch_2d(&mut luts_pass, settings.sky_view_lut_size);
140
141
// Aerial View LUT
142
143
luts_pass.set_pipeline(aerial_view_lut_pipeline);
144
luts_pass.set_bind_group(
145
0,
146
&bind_groups.aerial_view_lut,
147
&[
148
atmosphere_uniforms_offset.index(),
149
settings_uniforms_offset.index(),
150
view_uniforms_offset.offset,
151
lights_uniforms_offset.offset,
152
],
153
);
154
155
dispatch_2d(&mut luts_pass, settings.aerial_view_lut_size.xy());
156
157
pass_span.end(&mut luts_pass);
158
159
Ok(())
160
}
161
}
162
163
#[derive(Default)]
164
pub(super) struct RenderSkyNode;
165
166
impl ViewNode for RenderSkyNode {
167
type ViewQuery = (
168
Read<AtmosphereBindGroups>,
169
Read<ViewTarget>,
170
Read<DynamicUniformIndex<Atmosphere>>,
171
Read<DynamicUniformIndex<GpuAtmosphereSettings>>,
172
Read<AtmosphereTransformsOffset>,
173
Read<ViewUniformOffset>,
174
Read<ViewLightsUniformOffset>,
175
Read<RenderSkyPipelineId>,
176
);
177
178
fn run<'w>(
179
&self,
180
_graph: &mut RenderGraphContext,
181
render_context: &mut RenderContext<'w>,
182
(
183
atmosphere_bind_groups,
184
view_target,
185
atmosphere_uniforms_offset,
186
settings_uniforms_offset,
187
atmosphere_transforms_offset,
188
view_uniforms_offset,
189
lights_uniforms_offset,
190
render_sky_pipeline_id,
191
): QueryItem<'w, '_, Self::ViewQuery>,
192
world: &'w World,
193
) -> Result<(), NodeRunError> {
194
let pipeline_cache = world.resource::<PipelineCache>();
195
let Some(render_sky_pipeline) =
196
pipeline_cache.get_render_pipeline(render_sky_pipeline_id.0)
197
else {
198
return Ok(());
199
}; //TODO: warning
200
201
let diagnostics = render_context.diagnostic_recorder();
202
203
let mut render_sky_pass =
204
render_context
205
.command_encoder()
206
.begin_render_pass(&RenderPassDescriptor {
207
label: Some("render_sky"),
208
color_attachments: &[Some(view_target.get_color_attachment())],
209
depth_stencil_attachment: None,
210
timestamp_writes: None,
211
occlusion_query_set: None,
212
});
213
let pass_span = diagnostics.pass_span(&mut render_sky_pass, "render_sky");
214
215
render_sky_pass.set_pipeline(render_sky_pipeline);
216
render_sky_pass.set_bind_group(
217
0,
218
&atmosphere_bind_groups.render_sky,
219
&[
220
atmosphere_uniforms_offset.index(),
221
settings_uniforms_offset.index(),
222
atmosphere_transforms_offset.index(),
223
view_uniforms_offset.offset,
224
lights_uniforms_offset.offset,
225
],
226
);
227
render_sky_pass.draw(0..3, 0..1);
228
229
pass_span.end(&mut render_sky_pass);
230
231
Ok(())
232
}
233
}
234
235