1
1
use bevy::{
2
- core_pipeline::{SetItemPipeline, Transparent3d} ,
2
+ core_pipeline::Transparent3d,
3
3
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
4
4
ecs::{
5
5
prelude::*,
@@ -19,11 +19,12 @@ use bevy::{
19
19
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets},
20
20
render_component::ExtractComponentPlugin,
21
21
render_phase::{
22
- AddRenderCommand, DrawFunctions, RenderCommand, RenderPhase, TrackedRenderPass,
22
+ AddRenderCommand, DrawFunctions, EntityRenderCommand, RenderPhase, SetItemPipeline,
23
+ TrackedRenderPass,
23
24
},
24
25
render_resource::*,
25
26
renderer::RenderDevice,
26
- view::ExtractedView,
27
+ view::{ComputedVisibility, ExtractedView, Msaa, Visibility} ,
27
28
RenderApp, RenderStage,
28
29
},
29
30
PipelinedDefaultPlugins,
@@ -51,6 +52,8 @@ fn setup(
51
52
meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
52
53
Transform::from_xyz(0.0, 0.5, 0.0),
53
54
GlobalTransform::default(),
55
+ Visibility::default(),
56
+ ComputedVisibility::default(),
54
57
materials.add(CustomMaterial {
55
58
color: Color::GREEN,
56
59
}),
@@ -118,21 +121,36 @@ impl Plugin for CustomMaterialPlugin {
118
121
app.sub_app(RenderApp)
119
122
.add_render_command::<Transparent3d, DrawCustom>()
120
123
.init_resource::<CustomPipeline>()
124
+ .init_resource::<SpecializedPipelines<CustomPipeline>>()
121
125
.add_system_to_stage(RenderStage::Queue, queue_custom);
122
126
}
123
127
}
124
128
125
129
pub struct CustomPipeline {
126
130
material_layout: BindGroupLayout,
127
- pipeline: CachedPipelineId,
131
+ shader: Handle<Shader>,
132
+ pbr_pipeline: PbrPipeline,
133
+ }
134
+
135
+ impl SpecializedPipeline for CustomPipeline {
136
+ type Key = PbrPipelineKey;
137
+
138
+ fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
139
+ let mut descriptor = self.pbr_pipeline.specialize(key);
140
+ descriptor.vertex.shader = self.shader.clone();
141
+ descriptor.fragment.as_mut().unwrap().shader = self.shader.clone();
142
+ descriptor.layout = Some(vec![
143
+ self.pbr_pipeline.view_layout.clone(),
144
+ self.pbr_pipeline.mesh_layout.clone(),
145
+ self.material_layout.clone(),
146
+ ]);
147
+ descriptor
148
+ }
128
149
}
129
150
130
151
impl FromWorld for CustomPipeline {
131
152
fn from_world(world: &mut World) -> Self {
132
- let world = world.cell();
133
153
let asset_server = world.get_resource::<AssetServer>().unwrap();
134
- let shader = asset_server.load("shaders/custom.wgsl");
135
-
136
154
let render_device = world.get_resource::<RenderDevice>().unwrap();
137
155
let material_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
138
156
entries: &[BindGroupLayoutEntry {
@@ -148,43 +166,42 @@ impl FromWorld for CustomPipeline {
148
166
label: None,
149
167
});
150
168
151
- let pbr_pipeline = world.get_resource::<PbrPipeline>().unwrap();
152
- let mut descriptor = pbr_pipeline.specialize(PbrPipelineKey::empty());
153
- descriptor.vertex.shader = shader.clone();
154
- descriptor.fragment.as_mut().unwrap().shader = shader;
155
- descriptor.layout = Some(vec![
156
- pbr_pipeline.view_layout.clone(),
157
- material_layout.clone(),
158
- pbr_pipeline.mesh_layout.clone(),
159
- ]);
160
-
161
- let mut pipeline_cache = world.get_resource_mut::<RenderPipelineCache>().unwrap();
162
169
CustomPipeline {
163
- pipeline: pipeline_cache.queue(descriptor),
170
+ pbr_pipeline: world.get_resource::<PbrPipeline>().unwrap().clone(),
171
+ shader: asset_server.load("shaders/custom.wgsl"),
164
172
material_layout,
165
173
}
166
174
}
167
175
}
168
176
177
+ #[allow(clippy::too_many_arguments)]
169
178
pub fn queue_custom(
170
179
transparent_3d_draw_functions: Res<DrawFunctions<Transparent3d>>,
171
180
materials: Res<RenderAssets<CustomMaterial>>,
172
181
custom_pipeline: Res<CustomPipeline>,
182
+ mut pipeline_cache: ResMut<RenderPipelineCache>,
183
+ mut specialized_pipelines: ResMut<SpecializedPipelines<CustomPipeline>>,
184
+ msaa: Res<Msaa>,
173
185
material_meshes: Query<(Entity, &Handle<CustomMaterial>, &MeshUniform), With<Handle<Mesh>>>,
174
186
mut views: Query<(&ExtractedView, &mut RenderPhase<Transparent3d>)>,
175
187
) {
176
188
let draw_custom = transparent_3d_draw_functions
177
189
.read()
178
190
.get_id::<DrawCustom>()
179
191
.unwrap();
192
+ let key = PbrPipelineKey::from_msaa_samples(msaa.samples);
180
193
for (view, mut transparent_phase) in views.iter_mut() {
181
194
let view_matrix = view.transform.compute_matrix();
182
195
let view_row_2 = view_matrix.row(2);
183
196
for (entity, material_handle, mesh_uniform) in material_meshes.iter() {
184
197
if materials.contains_key(material_handle) {
185
198
transparent_phase.add(Transparent3d {
186
199
entity,
187
- pipeline: custom_pipeline.pipeline,
200
+ pipeline: specialized_pipelines.specialize(
201
+ &mut pipeline_cache,
202
+ &custom_pipeline,
203
+ key,
204
+ ),
188
205
draw_function: draw_custom,
189
206
distance: view_row_2.dot(mesh_uniform.transform.col(3)),
190
207
});
@@ -196,25 +213,25 @@ pub fn queue_custom(
196
213
type DrawCustom = (
197
214
SetItemPipeline,
198
215
SetMeshViewBindGroup<0>,
216
+ SetTransformBindGroup<1>,
199
217
SetCustomMaterialBindGroup,
200
- SetTransformBindGroup<2>,
201
218
DrawMesh,
202
219
);
203
220
204
221
struct SetCustomMaterialBindGroup;
205
- impl RenderCommand<Transparent3d> for SetCustomMaterialBindGroup {
222
+ impl EntityRenderCommand for SetCustomMaterialBindGroup {
206
223
type Param = (
207
224
SRes<RenderAssets<CustomMaterial>>,
208
225
SQuery<Read<Handle<CustomMaterial>>>,
209
226
);
210
227
fn render<'w>(
211
228
_view: Entity,
212
- item: &Transparent3d ,
229
+ item: Entity ,
213
230
(materials, query): SystemParamItem<'w, '_, Self::Param>,
214
231
pass: &mut TrackedRenderPass<'w>,
215
232
) {
216
- let material_handle = query.get(item.entity ).unwrap();
233
+ let material_handle = query.get(item).unwrap();
217
234
let material = materials.into_inner().get(material_handle).unwrap();
218
- pass.set_bind_group(1 , &material.bind_group, &[]);
235
+ pass.set_bind_group(2 , &material.bind_group, &[]);
219
236
}
220
237
}
0 commit comments