1use std::ops::Deref;
2
3use bevy_ecs::prelude::*;
4
5use crate::{
6 ResolutionInfo, WgpuContext,
7 primitives::{
8 mesh_items::MeshItemsBuffer,
9 viewport::{ViewportBindGroup, ViewportGpuPacket},
10 },
11 resource::{GpuResource, OUTPUT_TEXTURE_FORMAT, PipelinesPool},
12 schedule::{FrameTarget, RenderContext},
13};
14
15pub(crate) fn depth(
16 mut render: RenderContext,
17 ctx: Res<WgpuContext>,
18 pipelines: Res<PipelinesPool>,
19 resolution: Res<ResolutionInfo>,
20 target: Res<FrameTarget>,
21 viewport: Res<ViewportGpuPacket>,
22 merged: Res<MeshItemsBuffer>,
23) {
24 if merged.item_count() == 0 {
25 return;
26 }
27 let mut pass = render
28 .encoder()
29 .begin_render_pass(&wgpu::RenderPassDescriptor {
30 label: Some("Merged MeshItem Depth Render Pass"),
31 color_attachments: &[],
32 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
33 view: &target.depth_stencil_view,
34 depth_ops: Some(wgpu::Operations {
35 load: wgpu::LoadOp::Load,
36 store: wgpu::StoreOp::Store,
37 }),
38 stencil_ops: None,
39 }),
40 timestamp_writes: None,
41 occlusion_query_set: None,
42 multiview_mask: None,
43 });
44 pass.set_pipeline(&pipelines.get_or_init::<MeshItemDepthPipeline>(&ctx));
45 pass.set_bind_group(0, &resolution.bind_group, &[]);
46 pass.set_bind_group(1, &viewport.uniforms_bind_group.bind_group, &[]);
47 pass.set_bind_group(2, merged.render_bind_group.as_ref().unwrap(), &[]);
48 pass.set_vertex_buffer(0, merged.vertices_buffer.buffer.slice(..));
49 pass.set_vertex_buffer(1, merged.mesh_ids_buffer.buffer.slice(..));
50 pass.set_vertex_buffer(2, merged.vertex_colors_buffer.buffer.slice(..));
51 pass.set_vertex_buffer(3, merged.vertex_normals_buffer.buffer.slice(..));
52 pass.set_index_buffer(
53 merged.indices_buffer.buffer.slice(..),
54 wgpu::IndexFormat::Uint32,
55 );
56 pass.draw_indexed(0..merged.total_indices(), 0, 0..1);
57}
58
59pub(crate) fn color(
60 mut render: RenderContext,
61 ctx: Res<WgpuContext>,
62 pipelines: Res<PipelinesPool>,
63 resolution: Res<ResolutionInfo>,
64 target: Res<FrameTarget>,
65 viewport: Res<ViewportGpuPacket>,
66 merged: Res<MeshItemsBuffer>,
67) {
68 if merged.item_count() == 0 {
69 return;
70 }
71 let mut pass = render
72 .encoder()
73 .begin_render_pass(&wgpu::RenderPassDescriptor {
74 label: Some("Merged MeshItem Color Render Pass"),
75 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
76 view: &target.render_view,
77 resolve_target: None,
78 depth_slice: None,
79 ops: wgpu::Operations {
80 load: wgpu::LoadOp::Load,
81 store: wgpu::StoreOp::Store,
82 },
83 })],
84 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
85 view: &target.depth_stencil_view,
86 depth_ops: Some(wgpu::Operations {
87 load: wgpu::LoadOp::Load,
88 store: wgpu::StoreOp::Store,
89 }),
90 stencil_ops: None,
91 }),
92 timestamp_writes: None,
93 occlusion_query_set: None,
94 multiview_mask: None,
95 });
96 pass.set_pipeline(&pipelines.get_or_init::<MeshItemColorPipeline>(&ctx));
97 pass.set_bind_group(0, &resolution.bind_group, &[]);
98 pass.set_bind_group(1, &viewport.uniforms_bind_group.bind_group, &[]);
99 pass.set_bind_group(2, merged.render_bind_group.as_ref().unwrap(), &[]);
100 pass.set_vertex_buffer(0, merged.vertices_buffer.buffer.slice(..));
101 pass.set_vertex_buffer(1, merged.mesh_ids_buffer.buffer.slice(..));
102 pass.set_vertex_buffer(2, merged.vertex_colors_buffer.buffer.slice(..));
103 pass.set_vertex_buffer(3, merged.vertex_normals_buffer.buffer.slice(..));
104 pass.set_index_buffer(
105 merged.indices_buffer.buffer.slice(..),
106 wgpu::IndexFormat::Uint32,
107 );
108 pass.draw_indexed(0..merged.total_indices(), 0, 0..1);
109}
110
111pub struct MeshItemColorPipeline {
112 pipeline: wgpu::RenderPipeline,
113}
114
115impl Deref for MeshItemColorPipeline {
116 type Target = wgpu::RenderPipeline;
117 fn deref(&self) -> &Self::Target {
118 &self.pipeline
119 }
120}
121
122impl GpuResource for MeshItemColorPipeline {
123 fn new(ctx: &WgpuContext) -> Self {
124 let module = &ctx
125 .device
126 .create_shader_module(wgpu::include_wgsl!("./shaders/mesh_item.wgsl"));
127 let layout = ctx
128 .device
129 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
130 label: Some("MeshItem Color Pipeline Layout"),
131 bind_group_layouts: &[
132 Some(&ResolutionInfo::create_bind_group_layout(ctx)),
133 Some(&ViewportBindGroup::bind_group_layout(ctx)),
134 Some(&MeshItemsBuffer::render_bind_group_layout(ctx)),
135 ],
136 immediate_size: 0,
137 });
138 let vertex_buffer_layouts = MeshItemsBuffer::vertex_buffer_layouts().map(Some);
139 let pipeline = ctx
140 .device
141 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
142 label: Some("MeshItem Color Pipeline"),
143 layout: Some(&layout),
144 vertex: wgpu::VertexState {
145 module,
146 entry_point: Some("vs_main"),
147 buffers: &vertex_buffer_layouts,
148 compilation_options: wgpu::PipelineCompilationOptions::default(),
149 },
150 fragment: Some(wgpu::FragmentState {
151 module,
152 entry_point: Some("fs_color"),
153 compilation_options: wgpu::PipelineCompilationOptions::default(),
154 targets: &[Some(wgpu::ColorTargetState {
155 format: OUTPUT_TEXTURE_FORMAT,
156 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
157 write_mask: wgpu::ColorWrites::ALL,
158 })],
159 }),
160 primitive: wgpu::PrimitiveState {
161 topology: wgpu::PrimitiveTopology::TriangleList,
162 ..Default::default()
163 },
164 depth_stencil: Some(wgpu::DepthStencilState {
165 format: wgpu::TextureFormat::Depth32Float,
166 depth_write_enabled: Some(false),
167 depth_compare: Some(wgpu::CompareFunction::LessEqual),
168 stencil: wgpu::StencilState::default(),
169 bias: wgpu::DepthBiasState::default(),
170 }),
171 multisample: wgpu::MultisampleState {
172 count: 1,
173 mask: !0,
174 alpha_to_coverage_enabled: false,
175 },
176 multiview_mask: None,
177 cache: None,
178 });
179 Self { pipeline }
180 }
181}
182
183pub struct MeshItemDepthPipeline {
184 pipeline: wgpu::RenderPipeline,
185}
186
187impl Deref for MeshItemDepthPipeline {
188 type Target = wgpu::RenderPipeline;
189 fn deref(&self) -> &Self::Target {
190 &self.pipeline
191 }
192}
193
194impl GpuResource for MeshItemDepthPipeline {
195 fn new(ctx: &WgpuContext) -> Self {
196 let module = &ctx
197 .device
198 .create_shader_module(wgpu::include_wgsl!("./shaders/mesh_item.wgsl"));
199 let layout = ctx
200 .device
201 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
202 label: Some("MeshItem Depth Pipeline Layout"),
203 bind_group_layouts: &[
204 Some(&ResolutionInfo::create_bind_group_layout(ctx)),
205 Some(&ViewportBindGroup::bind_group_layout(ctx)),
206 Some(&MeshItemsBuffer::render_bind_group_layout(ctx)),
207 ],
208 immediate_size: 0,
209 });
210 let vertex_buffer_layouts = MeshItemsBuffer::vertex_buffer_layouts().map(Some);
211 let pipeline = ctx
212 .device
213 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
214 label: Some("MeshItem Depth Pipeline"),
215 layout: Some(&layout),
216 vertex: wgpu::VertexState {
217 module,
218 entry_point: Some("vs_main"),
219 buffers: &vertex_buffer_layouts,
220 compilation_options: wgpu::PipelineCompilationOptions::default(),
221 },
222 fragment: Some(wgpu::FragmentState {
223 module,
224 entry_point: Some("fs_depth"),
225 compilation_options: wgpu::PipelineCompilationOptions::default(),
226 targets: &[],
227 }),
228 primitive: wgpu::PrimitiveState {
229 topology: wgpu::PrimitiveTopology::TriangleList,
230 ..Default::default()
231 },
232 depth_stencil: Some(wgpu::DepthStencilState {
233 format: wgpu::TextureFormat::Depth32Float,
234 depth_write_enabled: Some(true),
235 depth_compare: Some(wgpu::CompareFunction::Less),
236 stencil: wgpu::StencilState::default(),
237 bias: wgpu::DepthBiasState::default(),
238 }),
239 multisample: wgpu::MultisampleState {
240 count: 1,
241 mask: !0,
242 alpha_to_coverage_enabled: false,
243 },
244 multiview_mask: None,
245 cache: None,
246 });
247 Self { pipeline }
248 }
249}