|
1 | 1 | use bevy_app::{App, Plugin};
|
2 |
| -use bevy_asset::{load_internal_asset, AssetServer, Assets, Handle, HandleUntyped}; |
3 |
| -use bevy_ecs::system::{lifetimeless::SRes, SystemParamItem}; |
| 2 | +use bevy_asset::{load_internal_asset, Assets, Handle, HandleUntyped}; |
4 | 3 | use bevy_math::Vec4;
|
5 | 4 | use bevy_reflect::TypeUuid;
|
6 | 5 | use bevy_render::{
|
7 |
| - color::Color, |
8 |
| - prelude::Shader, |
9 |
| - render_asset::{PrepareAssetError, RenderAsset, RenderAssets}, |
10 |
| - render_resource::*, |
11 |
| - renderer::RenderDevice, |
12 |
| - texture::Image, |
| 6 | + color::Color, prelude::Shader, render_asset::RenderAssets, render_resource::*, texture::Image, |
13 | 7 | };
|
14 | 8 |
|
15 |
| -use crate::{Material2d, Material2dPipeline, Material2dPlugin, MaterialMesh2dBundle}; |
| 9 | +use crate::{Material2d, Material2dPlugin, MaterialMesh2dBundle}; |
16 | 10 |
|
17 | 11 | pub const COLOR_MATERIAL_SHADER_HANDLE: HandleUntyped =
|
18 | 12 | HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 3253086872234592509);
|
@@ -44,10 +38,13 @@ impl Plugin for ColorMaterialPlugin {
|
44 | 38 | }
|
45 | 39 |
|
46 | 40 | /// A [2d material](Material2d) that renders [2d meshes](crate::Mesh2dHandle) with a texture tinted by a uniform color
|
47 |
| -#[derive(Debug, Clone, TypeUuid)] |
| 41 | +#[derive(AsBindGroup, Debug, Clone, TypeUuid)] |
48 | 42 | #[uuid = "e228a544-e3ca-4e1e-bb9d-4d8bc1ad8c19"]
|
| 43 | +#[uniform(0, ColorMaterialUniform)] |
49 | 44 | pub struct ColorMaterial {
|
50 | 45 | pub color: Color,
|
| 46 | + #[texture(1)] |
| 47 | + #[sampler(2)] |
51 | 48 | pub texture: Option<Handle<Image>>,
|
52 | 49 | }
|
53 | 50 |
|
@@ -90,142 +87,28 @@ bitflags::bitflags! {
|
90 | 87 |
|
91 | 88 | /// The GPU representation of the uniform data of a [`ColorMaterial`].
|
92 | 89 | #[derive(Clone, Default, ShaderType)]
|
93 |
| -pub struct ColorMaterialUniformData { |
| 90 | +pub struct ColorMaterialUniform { |
94 | 91 | pub color: Vec4,
|
95 | 92 | pub flags: u32,
|
96 | 93 | }
|
97 | 94 |
|
98 |
| -/// The GPU representation of a [`ColorMaterial`]. |
99 |
| -#[derive(Debug, Clone)] |
100 |
| -pub struct GpuColorMaterial { |
101 |
| - /// A buffer containing the [`ColorMaterialUniformData`] of the material. |
102 |
| - pub buffer: Buffer, |
103 |
| - /// The bind group specifying how the [`ColorMaterialUniformData`] and |
104 |
| - /// the texture of the material are bound. |
105 |
| - pub bind_group: BindGroup, |
106 |
| - pub flags: ColorMaterialFlags, |
107 |
| - pub texture: Option<Handle<Image>>, |
108 |
| -} |
109 |
| - |
110 |
| -impl RenderAsset for ColorMaterial { |
111 |
| - type ExtractedAsset = ColorMaterial; |
112 |
| - type PreparedAsset = GpuColorMaterial; |
113 |
| - type Param = ( |
114 |
| - SRes<RenderDevice>, |
115 |
| - SRes<Material2dPipeline<ColorMaterial>>, |
116 |
| - SRes<RenderAssets<Image>>, |
117 |
| - ); |
118 |
| - |
119 |
| - fn extract_asset(&self) -> Self::ExtractedAsset { |
120 |
| - self.clone() |
121 |
| - } |
122 |
| - |
123 |
| - fn prepare_asset( |
124 |
| - material: Self::ExtractedAsset, |
125 |
| - (render_device, color_pipeline, gpu_images): &mut SystemParamItem<Self::Param>, |
126 |
| - ) -> Result<Self::PreparedAsset, PrepareAssetError<Self::ExtractedAsset>> { |
127 |
| - let (texture_view, sampler) = if let Some(result) = color_pipeline |
128 |
| - .mesh2d_pipeline |
129 |
| - .get_image_texture(gpu_images, &material.texture) |
130 |
| - { |
131 |
| - result |
132 |
| - } else { |
133 |
| - return Err(PrepareAssetError::RetryNextUpdate(material)); |
134 |
| - }; |
135 |
| - |
| 95 | +impl AsBindGroupShaderType<ColorMaterialUniform> for ColorMaterial { |
| 96 | + fn as_bind_group_shader_type(&self, _images: &RenderAssets<Image>) -> ColorMaterialUniform { |
136 | 97 | let mut flags = ColorMaterialFlags::NONE;
|
137 |
| - if material.texture.is_some() { |
| 98 | + if self.texture.is_some() { |
138 | 99 | flags |= ColorMaterialFlags::TEXTURE;
|
139 | 100 | }
|
140 | 101 |
|
141 |
| - let value = ColorMaterialUniformData { |
142 |
| - color: material.color.as_linear_rgba_f32().into(), |
| 102 | + ColorMaterialUniform { |
| 103 | + color: self.color.as_linear_rgba_f32().into(), |
143 | 104 | flags: flags.bits(),
|
144 |
| - }; |
145 |
| - |
146 |
| - let byte_buffer = [0u8; ColorMaterialUniformData::SHADER_SIZE.get() as usize]; |
147 |
| - let mut buffer = encase::UniformBuffer::new(byte_buffer); |
148 |
| - buffer.write(&value).unwrap(); |
149 |
| - |
150 |
| - let buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { |
151 |
| - label: Some("color_material_uniform_buffer"), |
152 |
| - usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST, |
153 |
| - contents: buffer.as_ref(), |
154 |
| - }); |
155 |
| - let bind_group = render_device.create_bind_group(&BindGroupDescriptor { |
156 |
| - entries: &[ |
157 |
| - BindGroupEntry { |
158 |
| - binding: 0, |
159 |
| - resource: buffer.as_entire_binding(), |
160 |
| - }, |
161 |
| - BindGroupEntry { |
162 |
| - binding: 1, |
163 |
| - resource: BindingResource::TextureView(texture_view), |
164 |
| - }, |
165 |
| - BindGroupEntry { |
166 |
| - binding: 2, |
167 |
| - resource: BindingResource::Sampler(sampler), |
168 |
| - }, |
169 |
| - ], |
170 |
| - label: Some("color_material_bind_group"), |
171 |
| - layout: &color_pipeline.material2d_layout, |
172 |
| - }); |
173 |
| - |
174 |
| - Ok(GpuColorMaterial { |
175 |
| - buffer, |
176 |
| - bind_group, |
177 |
| - flags, |
178 |
| - texture: material.texture, |
179 |
| - }) |
| 105 | + } |
180 | 106 | }
|
181 | 107 | }
|
182 | 108 |
|
183 | 109 | impl Material2d for ColorMaterial {
|
184 |
| - fn fragment_shader(_asset_server: &AssetServer) -> Option<Handle<Shader>> { |
185 |
| - Some(COLOR_MATERIAL_SHADER_HANDLE.typed()) |
186 |
| - } |
187 |
| - |
188 |
| - #[inline] |
189 |
| - fn bind_group(render_asset: &<Self as RenderAsset>::PreparedAsset) -> &BindGroup { |
190 |
| - &render_asset.bind_group |
191 |
| - } |
192 |
| - |
193 |
| - fn bind_group_layout( |
194 |
| - render_device: &RenderDevice, |
195 |
| - ) -> bevy_render::render_resource::BindGroupLayout { |
196 |
| - render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { |
197 |
| - entries: &[ |
198 |
| - BindGroupLayoutEntry { |
199 |
| - binding: 0, |
200 |
| - visibility: ShaderStages::FRAGMENT, |
201 |
| - ty: BindingType::Buffer { |
202 |
| - ty: BufferBindingType::Uniform, |
203 |
| - has_dynamic_offset: false, |
204 |
| - min_binding_size: Some(ColorMaterialUniformData::min_size()), |
205 |
| - }, |
206 |
| - count: None, |
207 |
| - }, |
208 |
| - // Texture |
209 |
| - BindGroupLayoutEntry { |
210 |
| - binding: 1, |
211 |
| - visibility: ShaderStages::FRAGMENT, |
212 |
| - ty: BindingType::Texture { |
213 |
| - multisampled: false, |
214 |
| - sample_type: TextureSampleType::Float { filterable: true }, |
215 |
| - view_dimension: TextureViewDimension::D2, |
216 |
| - }, |
217 |
| - count: None, |
218 |
| - }, |
219 |
| - // Texture Sampler |
220 |
| - BindGroupLayoutEntry { |
221 |
| - binding: 2, |
222 |
| - visibility: ShaderStages::FRAGMENT, |
223 |
| - ty: BindingType::Sampler(SamplerBindingType::Filtering), |
224 |
| - count: None, |
225 |
| - }, |
226 |
| - ], |
227 |
| - label: Some("color_material_layout"), |
228 |
| - }) |
| 110 | + fn fragment_shader() -> ShaderRef { |
| 111 | + COLOR_MATERIAL_SHADER_HANDLE.typed().into() |
229 | 112 | }
|
230 | 113 | }
|
231 | 114 |
|
|
0 commit comments