mirror of
https://github.com/bevyengine/bevy
synced 2024-11-27 07:00:18 +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;
|
||||||
pub mod material_data;
|
pub mod material_data;
|
||||||
pub mod material_pipeline;
|
pub mod material_pipeline;
|
||||||
|
pub mod shaders;
|
||||||
|
pub mod specialize;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use super::material::{Material, MaterialPlugin};
|
pub use super::material::{Material, MaterialPlugin};
|
||||||
|
@ -21,14 +23,4 @@ mod tests {
|
||||||
pub struct TestPipeline;
|
pub struct TestPipeline;
|
||||||
|
|
||||||
type TestMaterial<M> = MaterialComponent<M, 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},
|
system::{lifetimeless::SRes, SystemParamItem},
|
||||||
world::{FromWorld, World},
|
world::{FromWorld, World},
|
||||||
};
|
};
|
||||||
use bevy_utils::HashMap;
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use bevy_app::{App, Plugin};
|
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_derive::{Deref, DerefMut};
|
||||||
use bevy_ecs::system::{Query, ResMut, Resource};
|
use bevy_ecs::system::{Query, ResMut, Resource};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin},
|
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin},
|
||||||
render_resource::{AsBindGroup, AsBindGroupError, BindGroupLayout, PreparedBindGroup, Shader},
|
render_resource::{AsBindGroup, AsBindGroupError, BindGroupLayout, PreparedBindGroup},
|
||||||
renderer::RenderDevice,
|
renderer::RenderDevice,
|
||||||
sync_world::{MainEntity, MainEntityHashMap},
|
sync_world::{MainEntity, MainEntityHashMap},
|
||||||
view::ViewVisibility,
|
view::ViewVisibility,
|
||||||
Extract, ExtractSchedule, RenderApp,
|
Extract, ExtractSchedule, RenderApp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::component::MaterialComponent;
|
|
||||||
use crate::material_pipeline::MaterialPipeline;
|
use crate::material_pipeline::MaterialPipeline;
|
||||||
|
use crate::{
|
||||||
|
component::MaterialComponent,
|
||||||
|
shaders::{LoadedShaders, Shaders},
|
||||||
|
};
|
||||||
|
|
||||||
pub enum SpecializeMaterialError {}
|
pub enum SpecializeMaterialError {}
|
||||||
|
|
||||||
|
@ -34,24 +36,6 @@ pub trait Material<P: MaterialPipeline>: BaseMaterial {
|
||||||
fn specialize(ctx: P::PipelineContext<'_, Self>) -> Result<(), SpecializeMaterialError>;
|
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)>);
|
pub struct MaterialPlugin<M: Material<P>, P: MaterialPipeline>(PhantomData<fn(M, P)>);
|
||||||
|
|
||||||
impl<M: Material<P>, P: MaterialPipeline> Default for MaterialPlugin<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> {
|
pub struct MaterialProperties<M: Material<R>, R: MaterialPipeline> {
|
||||||
#[deref]
|
#[deref]
|
||||||
properties: R::MaterialProperties,
|
properties: R::MaterialProperties,
|
||||||
_data: PhantomData<M>,
|
_data: PhantomData<fn(M)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: Material<R>, R: MaterialPipeline> MaterialProperties<M, R> {
|
impl<M: Material<R>, R: MaterialPipeline> MaterialProperties<M, R> {
|
||||||
|
@ -191,19 +175,18 @@ impl<M: BaseMaterial> FromWorld for MaterialLayout<M> {
|
||||||
#[derive(Deref, Resource)]
|
#[derive(Deref, Resource)]
|
||||||
pub struct MaterialShaders<M: Material<P>, P: MaterialPipeline> {
|
pub struct MaterialShaders<M: Material<P>, P: MaterialPipeline> {
|
||||||
#[deref]
|
#[deref]
|
||||||
shaders: HashMap<P::ShaderKey, Handle<Shader>>,
|
shaders: LoadedShaders<P>,
|
||||||
_data: PhantomData<fn(M)>,
|
_data: PhantomData<fn(M)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: Material<P>, P: MaterialPipeline> FromWorld for MaterialShaders<M, P> {
|
impl<M: Material<P>, P: MaterialPipeline> FromWorld for MaterialShaders<M, P> {
|
||||||
fn from_world(world: &mut World) -> Self {
|
fn from_world(world: &mut World) -> Self {
|
||||||
let asset_server = world.resource::<AssetServer>();
|
let asset_server = world.resource::<AssetServer>();
|
||||||
|
let mut shaders = P::default_shaders();
|
||||||
|
shaders.extend(M::shaders());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
shaders: M::shaders()
|
shaders: shaders.load(asset_server),
|
||||||
.shaders
|
|
||||||
.into_iter()
|
|
||||||
.map(|(key, path)| (key, asset_server.load(path)))
|
|
||||||
.collect(),
|
|
||||||
_data: PhantomData,
|
_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> {
|
impl<'w, M: Material<P>, P: MaterialPipeline> MaterialData<'w, M, P> {
|
||||||
pub fn get(
|
pub fn get(&self, main_entity: MainEntity, id: AssetId<M>) -> Option<MaterialInstance<M, P>> {
|
||||||
&self,
|
|
||||||
main_entity: MainEntity,
|
|
||||||
id: AssetId<M>,
|
|
||||||
) -> Option<PreparedMaterialInstance<M, P>> {
|
|
||||||
let bind_group = self.bind_groups.get(id)?;
|
let bind_group = self.bind_groups.get(id)?;
|
||||||
let properties = self.properties.get(id)?;
|
let properties = self.properties.get(id)?;
|
||||||
Some(PreparedMaterialInstance {
|
Some(MaterialInstance {
|
||||||
main_entity,
|
main_entity,
|
||||||
layout: &self.layout,
|
layout: &self.layout,
|
||||||
shaders: &self.shaders,
|
shaders: &self.shaders,
|
||||||
|
@ -42,14 +38,14 @@ impl<'w, M: Material<P>, P: MaterialPipeline> MaterialData<'w, M, P> {
|
||||||
pub fn iter<'a>(
|
pub fn iter<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
instances: &'a MaterialInstances<M, P>,
|
instances: &'a MaterialInstances<M, P>,
|
||||||
) -> impl Iterator<Item = PreparedMaterialInstance<'a, M, P>> + 'a {
|
) -> impl Iterator<Item = MaterialInstance<'a, M, P>> {
|
||||||
instances
|
instances
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(main_entity, material_id)| self.get(*main_entity, *material_id))
|
.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 main_entity: MainEntity,
|
||||||
pub properties: &'a P::MaterialProperties,
|
pub properties: &'a P::MaterialProperties,
|
||||||
pub shaders: &'a MaterialShaders<M, P>,
|
pub shaders: &'a MaterialShaders<M, P>,
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
use bevy_app::Plugin;
|
use bevy_app::Plugin;
|
||||||
|
use bevy_ecs::system::{ReadOnlySystemParam, SystemParamItem};
|
||||||
use bevy_reflect::TypePath;
|
use bevy_reflect::TypePath;
|
||||||
use core::hash::Hash;
|
use core::hash::Hash;
|
||||||
|
|
||||||
use crate::material::Material;
|
use crate::{material::Material, shaders::Shaders};
|
||||||
|
|
||||||
pub trait MaterialPipeline: TypePath + Sized + 'static {
|
pub trait MaterialPipeline: TypePath + Sized + 'static {
|
||||||
type MaterialProperties: Send + Sync + 'static;
|
type MaterialProperties: Send + Sync;
|
||||||
type ShaderKey: Hash + Eq + Send + Sync + 'static;
|
type ShaderKey: Hash + Eq + Send + Sync;
|
||||||
type PipelineContext<'a, M: Material<Self>>;
|
type PipelineContext<'a, M: Material<Self>>;
|
||||||
|
|
||||||
|
fn default_shaders() -> Shaders<Self>;
|
||||||
|
|
||||||
fn material_plugin<M: Material<Self>>() -> impl Plugin;
|
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