|
| 1 | +use crate::alpha::AlphaMode; |
| 2 | +use crate::opaque::OpaqueRendererMethod; |
| 3 | +use crate::render::MeshPipeline; |
1 | 4 | use crate::render::MeshPipelineKey; |
| 5 | +use crate::render_phase::{DrawFunctionId, DrawFunctionLabel, InternedDrawFunctionLabel, InternedShaderLabel, ShaderLabel}; |
| 6 | +use crate::render_resource::{BindGroupLayoutDescriptor, RenderPipelineDescriptor, SpecializedMeshPipelineError}; |
2 | 7 | use crate::*; |
3 | 8 | use alloc::sync::Arc; |
| 9 | +use bevy_asset::Handle; |
| 10 | +use bevy_ecs::resource::Resource; |
| 11 | +use bevy_mesh::MeshVertexBufferLayoutRef; |
4 | 12 | use bevy_platform::hash::FixedHasher; |
| 13 | +use bevy_shader::Shader; |
| 14 | +use smallvec::SmallVec; |
5 | 15 | use core::any::{Any, TypeId}; |
6 | 16 | use core::hash::{BuildHasher, Hasher}; |
7 | 17 | use core::hash::Hash; |
8 | 18 |
|
9 | 19 | pub const MATERIAL_BIND_GROUP_INDEX: usize = 3; |
10 | 20 |
|
| 21 | +/// Render pipeline data for a given [`Material`]. |
| 22 | +#[derive(Resource, Clone)] |
| 23 | +pub struct MaterialPipeline { |
| 24 | + pub mesh_pipeline: MeshPipeline, |
| 25 | +} |
| 26 | + |
11 | 27 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
12 | 28 | pub struct ErasedMaterialPipelineKey { |
13 | 29 | pub mesh_key: MeshPipelineKey, |
@@ -94,7 +110,84 @@ impl Default for ErasedMaterialKey { |
94 | 110 | } |
95 | 111 | } |
96 | 112 |
|
97 | | -// pub struct MaterialProperties { |
| 113 | +/// Common [`Material`] properties, calculated for a specific material instance. |
| 114 | +#[derive(Default)] |
| 115 | +pub struct MaterialProperties { |
| 116 | + /// Is this material should be rendered by the deferred renderer when. |
| 117 | + /// [`AlphaMode::Opaque`] or [`AlphaMode::Mask`] |
| 118 | + pub render_method: OpaqueRendererMethod, |
| 119 | + /// The [`AlphaMode`] of this material. |
| 120 | + pub alpha_mode: AlphaMode, |
| 121 | + /// The bits in the [`MeshPipelineKey`] for this material. |
| 122 | + /// |
| 123 | + /// These are precalculated so that we can just "or" them together in |
| 124 | + /// [`queue_material_meshes`]. |
| 125 | + pub mesh_pipeline_key_bits: MeshPipelineKey, |
| 126 | + /// Add a bias to the view depth of the mesh which can be used to force a specific render order |
| 127 | + /// for meshes with equal depth, to avoid z-fighting. |
| 128 | + /// The bias is in depth-texture units so large values may be needed to overcome small depth differences. |
| 129 | + pub depth_bias: f32, |
| 130 | + /// Whether the material would like to read from [`ViewTransmissionTexture`](bevy_core_pipeline::core_3d::ViewTransmissionTexture). |
| 131 | + /// |
| 132 | + /// This allows taking color output from the [`Opaque3d`] pass as an input, (for screen-space transmission) but requires |
| 133 | + /// rendering to take place in a separate [`Transmissive3d`] pass. |
| 134 | + pub reads_view_transmission_texture: bool, |
| 135 | + pub render_phase_type: RenderPhaseType, |
| 136 | + pub material_layout: Option<BindGroupLayoutDescriptor>, |
| 137 | + /// Backing array is a size of 4 because the `StandardMaterial` needs 4 draw functions by default |
| 138 | + pub draw_functions: SmallVec<[(InternedDrawFunctionLabel, DrawFunctionId); 4]>, |
| 139 | + /// Backing array is a size of 3 because the `StandardMaterial` has 3 custom shaders (`frag`, `prepass_frag`, `deferred_frag`) which is the |
| 140 | + /// most common use case |
| 141 | + pub shaders: SmallVec<[(InternedShaderLabel, Handle<Shader>); 3]>, |
| 142 | + /// Whether this material *actually* uses bindless resources, taking the |
| 143 | + /// platform support (or lack thereof) of bindless resources into account. |
| 144 | + pub bindless: bool, |
| 145 | + pub specialize: Option< |
| 146 | + fn( |
| 147 | + &MaterialPipeline, |
| 148 | + &mut RenderPipelineDescriptor, |
| 149 | + &MeshVertexBufferLayoutRef, |
| 150 | + ErasedMaterialPipelineKey, |
| 151 | + ) -> Result<(), SpecializedMeshPipelineError>, |
| 152 | + >, |
| 153 | + /// The key for this material, typically a bitfield of flags that are used to modify |
| 154 | + /// the pipeline descriptor used for this material. |
| 155 | + pub material_key: ErasedMaterialKey, |
| 156 | + /// Whether shadows are enabled for this material |
| 157 | + pub shadows_enabled: bool, |
| 158 | + /// Whether prepass is enabled for this material |
| 159 | + pub prepass_enabled: bool, |
| 160 | +} |
| 161 | + |
| 162 | +impl MaterialProperties { |
| 163 | + pub fn get_shader(&self, label: impl ShaderLabel) -> Option<Handle<Shader>> { |
| 164 | + self.shaders |
| 165 | + .iter() |
| 166 | + .find(|(inner_label, _)| inner_label == &label.intern()) |
| 167 | + .map(|(_, shader)| shader) |
| 168 | + .cloned() |
| 169 | + } |
| 170 | + |
| 171 | + pub fn add_shader(&mut self, label: impl ShaderLabel, shader: Handle<Shader>) { |
| 172 | + self.shaders.push((label.intern(), shader)); |
| 173 | + } |
| 174 | + |
| 175 | + pub fn get_draw_function(&self, label: impl DrawFunctionLabel) -> Option<DrawFunctionId> { |
| 176 | + self.draw_functions |
| 177 | + .iter() |
| 178 | + .find(|(inner_label, _)| inner_label == &label.intern()) |
| 179 | + .map(|(_, shader)| shader) |
| 180 | + .cloned() |
| 181 | + } |
| 182 | + |
| 183 | + pub fn add_draw_function( |
| 184 | + &mut self, |
| 185 | + label: impl DrawFunctionLabel, |
| 186 | + draw_function: DrawFunctionId, |
| 187 | + ) { |
| 188 | + self.draw_functions.push((label.intern(), draw_function)); |
| 189 | + } |
| 190 | +} |
98 | 191 |
|
99 | 192 | #[derive(Clone, Copy, Default)] |
100 | 193 | pub enum RenderPhaseType { |
|
0 commit comments