mirror of
https://github.com/bevyengine/bevy
synced 2024-11-23 13:13:49 +00:00
arghhh
This commit is contained in:
parent
8d90624061
commit
430447c943
6 changed files with 120 additions and 50 deletions
|
@ -2,6 +2,8 @@ pub mod component;
|
|||
pub mod material;
|
||||
pub mod material_data;
|
||||
pub mod material_pipeline;
|
||||
pub mod shaders;
|
||||
pub mod specialize;
|
||||
|
||||
pub mod prelude {
|
||||
pub use super::material::{Material, MaterialPlugin};
|
||||
|
@ -21,14 +23,4 @@ mod tests {
|
|||
pub struct TestPipeline;
|
||||
|
||||
type TestMaterial<M> = MaterialComponent<M, TestPipeline>;
|
||||
|
||||
impl MaterialPipeline for TestPipeline {
|
||||
type MaterialProperties = ();
|
||||
type ShaderKey = ();
|
||||
type PipelineContext<'a, M: Material<Self>> = ();
|
||||
|
||||
fn material_plugin<M: Material<Self>>() -> impl Plugin {
|
||||
|_: &mut App| {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,24 +3,26 @@ use bevy_ecs::{
|
|||
system::{lifetimeless::SRes, SystemParamItem},
|
||||
world::{FromWorld, World},
|
||||
};
|
||||
use bevy_utils::HashMap;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_asset::{Asset, AssetApp, AssetId, AssetPath, AssetServer, Handle};
|
||||
use bevy_asset::{Asset, AssetApp, AssetId, AssetServer};
|
||||
use bevy_derive::{Deref, DerefMut};
|
||||
use bevy_ecs::system::{Query, ResMut, Resource};
|
||||
use bevy_render::{
|
||||
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin},
|
||||
render_resource::{AsBindGroup, AsBindGroupError, BindGroupLayout, PreparedBindGroup, Shader},
|
||||
render_resource::{AsBindGroup, AsBindGroupError, BindGroupLayout, PreparedBindGroup},
|
||||
renderer::RenderDevice,
|
||||
sync_world::{MainEntity, MainEntityHashMap},
|
||||
view::ViewVisibility,
|
||||
Extract, ExtractSchedule, RenderApp,
|
||||
};
|
||||
|
||||
use crate::component::MaterialComponent;
|
||||
use crate::material_pipeline::MaterialPipeline;
|
||||
use crate::{
|
||||
component::MaterialComponent,
|
||||
shaders::{LoadedShaders, Shaders},
|
||||
};
|
||||
|
||||
pub enum SpecializeMaterialError {}
|
||||
|
||||
|
@ -34,24 +36,6 @@ pub trait Material<P: MaterialPipeline>: BaseMaterial {
|
|||
fn specialize(ctx: P::PipelineContext<'_, Self>) -> Result<(), SpecializeMaterialError>;
|
||||
}
|
||||
|
||||
#[derive(Deref)]
|
||||
pub struct Shaders<P: MaterialPipeline> {
|
||||
shaders: HashMap<P::ShaderKey, AssetPath<'static>>,
|
||||
}
|
||||
|
||||
impl<P: MaterialPipeline, A: Into<AssetPath<'static>>> FromIterator<(P::ShaderKey, A)>
|
||||
for Shaders<P>
|
||||
{
|
||||
fn from_iter<T: IntoIterator<Item = (P::ShaderKey, A)>>(iter: T) -> Self {
|
||||
Self {
|
||||
shaders: iter
|
||||
.into_iter()
|
||||
.map(|(key, path)| (key, path.into()))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MaterialPlugin<M: Material<P>, P: MaterialPipeline>(PhantomData<fn(M, P)>);
|
||||
|
||||
impl<M: Material<P>, P: MaterialPipeline> Default for MaterialPlugin<M, P> {
|
||||
|
@ -146,7 +130,7 @@ impl<M: BaseMaterial> RenderAsset for MaterialBindGroup<M> {
|
|||
pub struct MaterialProperties<M: Material<R>, R: MaterialPipeline> {
|
||||
#[deref]
|
||||
properties: R::MaterialProperties,
|
||||
_data: PhantomData<M>,
|
||||
_data: PhantomData<fn(M)>,
|
||||
}
|
||||
|
||||
impl<M: Material<R>, R: MaterialPipeline> MaterialProperties<M, R> {
|
||||
|
@ -191,19 +175,18 @@ impl<M: BaseMaterial> FromWorld for MaterialLayout<M> {
|
|||
#[derive(Deref, Resource)]
|
||||
pub struct MaterialShaders<M: Material<P>, P: MaterialPipeline> {
|
||||
#[deref]
|
||||
shaders: HashMap<P::ShaderKey, Handle<Shader>>,
|
||||
shaders: LoadedShaders<P>,
|
||||
_data: PhantomData<fn(M)>,
|
||||
}
|
||||
|
||||
impl<M: Material<P>, P: MaterialPipeline> FromWorld for MaterialShaders<M, P> {
|
||||
fn from_world(world: &mut World) -> Self {
|
||||
let asset_server = world.resource::<AssetServer>();
|
||||
let mut shaders = P::default_shaders();
|
||||
shaders.extend(M::shaders());
|
||||
|
||||
Self {
|
||||
shaders: M::shaders()
|
||||
.shaders
|
||||
.into_iter()
|
||||
.map(|(key, path)| (key, asset_server.load(path)))
|
||||
.collect(),
|
||||
shaders: shaders.load(asset_server),
|
||||
_data: PhantomData,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,14 +23,10 @@ pub struct MaterialData<'w, M: Material<P>, P: MaterialPipeline> {
|
|||
}
|
||||
|
||||
impl<'w, M: Material<P>, P: MaterialPipeline> MaterialData<'w, M, P> {
|
||||
pub fn get(
|
||||
&self,
|
||||
main_entity: MainEntity,
|
||||
id: AssetId<M>,
|
||||
) -> Option<PreparedMaterialInstance<M, P>> {
|
||||
pub fn get(&self, main_entity: MainEntity, id: AssetId<M>) -> Option<MaterialInstance<M, P>> {
|
||||
let bind_group = self.bind_groups.get(id)?;
|
||||
let properties = self.properties.get(id)?;
|
||||
Some(PreparedMaterialInstance {
|
||||
Some(MaterialInstance {
|
||||
main_entity,
|
||||
layout: &self.layout,
|
||||
shaders: &self.shaders,
|
||||
|
@ -42,14 +38,14 @@ impl<'w, M: Material<P>, P: MaterialPipeline> MaterialData<'w, M, P> {
|
|||
pub fn iter<'a>(
|
||||
&'a self,
|
||||
instances: &'a MaterialInstances<M, P>,
|
||||
) -> impl Iterator<Item = PreparedMaterialInstance<'a, M, P>> + 'a {
|
||||
) -> impl Iterator<Item = MaterialInstance<'a, M, P>> {
|
||||
instances
|
||||
.iter()
|
||||
.filter_map(|(main_entity, material_id)| self.get(*main_entity, *material_id))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PreparedMaterialInstance<'a, M: Material<P>, P: MaterialPipeline> {
|
||||
pub struct MaterialInstance<'a, M: Material<P>, P: MaterialPipeline> {
|
||||
pub main_entity: MainEntity,
|
||||
pub properties: &'a P::MaterialProperties,
|
||||
pub shaders: &'a MaterialShaders<M, P>,
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
use bevy_app::Plugin;
|
||||
use bevy_ecs::system::{ReadOnlySystemParam, SystemParamItem};
|
||||
use bevy_reflect::TypePath;
|
||||
use core::hash::Hash;
|
||||
|
||||
use crate::material::Material;
|
||||
use crate::{material::Material, shaders::Shaders};
|
||||
|
||||
pub trait MaterialPipeline: TypePath + Sized + 'static {
|
||||
type MaterialProperties: Send + Sync + 'static;
|
||||
type ShaderKey: Hash + Eq + Send + Sync + 'static;
|
||||
type MaterialProperties: Send + Sync;
|
||||
type ShaderKey: Hash + Eq + Send + Sync;
|
||||
type PipelineContext<'a, M: Material<Self>>;
|
||||
|
||||
fn default_shaders() -> Shaders<Self>;
|
||||
|
||||
fn material_plugin<M: Material<Self>>() -> impl Plugin;
|
||||
}
|
||||
|
|
75
crates/bevy_material/src/shaders.rs
Normal file
75
crates/bevy_material/src/shaders.rs
Normal file
|
@ -0,0 +1,75 @@
|
|||
use bevy_asset::{AssetPath, AssetServer, Handle};
|
||||
use bevy_derive::{Deref, DerefMut};
|
||||
use bevy_render::render_resource::Shader;
|
||||
use bevy_utils::HashMap;
|
||||
|
||||
use crate::material_pipeline::MaterialPipeline;
|
||||
|
||||
#[derive(Deref, DerefMut, Clone)]
|
||||
pub struct Shaders<P: MaterialPipeline> {
|
||||
shaders: HashMap<P::ShaderKey, AssetPath<'static>>,
|
||||
}
|
||||
|
||||
impl<P: MaterialPipeline> Default for Shaders<P> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
shaders: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: MaterialPipeline, A: Into<AssetPath<'static>>> FromIterator<(P::ShaderKey, A)>
|
||||
for Shaders<P>
|
||||
{
|
||||
fn from_iter<T: IntoIterator<Item = (P::ShaderKey, A)>>(iter: T) -> Self {
|
||||
Self {
|
||||
shaders: iter
|
||||
.into_iter()
|
||||
.map(|(key, path)| (key, path.into()))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: MaterialPipeline> Shaders<P> {
|
||||
pub fn new(iter: impl IntoIterator<Item = (P::ShaderKey, AssetPath<'static>)>) -> Self {
|
||||
Self::from_iter(iter)
|
||||
}
|
||||
|
||||
pub fn extend(&mut self, other: Shaders<P>) {
|
||||
self.shaders.extend(other.shaders.into_iter());
|
||||
}
|
||||
|
||||
pub fn load(self, asset_server: &AssetServer) -> LoadedShaders<P> {
|
||||
self.shaders
|
||||
.into_iter()
|
||||
.map(|(key, path)| (key, asset_server.load(path)))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deref)]
|
||||
pub struct LoadedShaders<P: MaterialPipeline> {
|
||||
shaders: HashMap<P::ShaderKey, Handle<Shader>>,
|
||||
}
|
||||
|
||||
impl<P: MaterialPipeline> FromIterator<(P::ShaderKey, Handle<Shader>)> for LoadedShaders<P> {
|
||||
fn from_iter<T: IntoIterator<Item = (P::ShaderKey, Handle<Shader>)>>(iter: T) -> Self {
|
||||
Self {
|
||||
shaders: iter
|
||||
.into_iter()
|
||||
.map(|(key, path)| (key, path.into()))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: MaterialPipeline> LoadedShaders<P> {
|
||||
pub fn new(iter: impl IntoIterator<Item = (P::ShaderKey, Handle<Shader>)>) -> Self {
|
||||
Self::from_iter(iter)
|
||||
}
|
||||
|
||||
pub fn extend(&mut self, other: LoadedShaders<P>) {
|
||||
self.shaders.extend(other.shaders.into_iter());
|
||||
}
|
||||
}
|
21
crates/bevy_material/src/specialize.rs
Normal file
21
crates/bevy_material/src/specialize.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
use bevy_ecs::system::ReadOnlySystemParam;
|
||||
use bevy_utils::HashMap;
|
||||
use core::{hash::Hash, marker::PhantomData};
|
||||
|
||||
use crate::{material::Material, material_pipeline::MaterialPipeline};
|
||||
|
||||
pub trait Specialize {
|
||||
type Key: Clone + Hash + Eq + Send + Sync;
|
||||
type Item: Send + Sync;
|
||||
}
|
||||
|
||||
pub type SpecializeMaterialContext<'a, M, P> =
|
||||
<<P as MaterialPipeline>::Specializer<M> as SpecializeMaterial>::Context<'a>;
|
||||
|
||||
pub struct Specializer<T: Specialize> {
|
||||
items: HashMap<T::Key, T::Item>,
|
||||
}
|
||||
|
||||
impl<T: Specialize> Specializer<T> {}
|
||||
|
||||
pub struct SpecializedMaterial<M: Material<P>, P: MaterialPipeline>(PhantomData<fn(M, P)>);
|
Loading…
Reference in a new issue