use bevy::app::App;
use bevy::asset::{Asset, Handle};
use bevy::mesh::MeshVertexBufferLayoutRef;
use bevy::pbr::{ExtendedMaterial, MaterialExtension, MaterialExtensionKey, MaterialExtensionPipeline, StandardMaterial};
use bevy::reflect::Reflect;
use bevy::render::render_resource::{AsBindGroup, RenderPipelineDescriptor, SpecializedMeshPipelineError};
use bevy::render::storage::ShaderBuffer;
use bevy::shader::ShaderRef;
use super::{ATTRIBUTE_GROWTH_AXIS, ATTRIBUTE_GROWTH_ID, ATTRIBUTE_GROWTH_OFFSET};
use crate::shading::{FloraKey, FloraUniform, specialize_flora};
pub type GrowthMaterial = ExtendedMaterial<StandardMaterial, GrowthExtension>;
#[derive(Asset, AsBindGroup, Reflect, Debug, Clone)]
#[bind_group_data(FloraKey)]
pub struct GrowthExtension {
#[storage(100, read_only)]
pub nodes: Handle<ShaderBuffer>,
#[uniform(101)]
pub flora: FloraUniform,
#[storage(102, read_only)]
pub wind: Handle<ShaderBuffer>,
pub leaf: bool,
}
impl From<&GrowthExtension> for FloraKey {
fn from(extension: &GrowthExtension) -> Self {
Self { leaf: extension.leaf }
}
}
impl MaterialExtension for GrowthExtension {
fn vertex_shader() -> ShaderRef {
"embedded://bevy_flora/gpu/growth.wesl".into()
}
fn prepass_vertex_shader() -> ShaderRef {
"embedded://bevy_flora/gpu/growth_prepass.wesl".into()
}
fn fragment_shader() -> ShaderRef {
"embedded://bevy_flora/shading/fragment.wesl".into()
}
fn specialize(
_pipeline: &MaterialExtensionPipeline,
descriptor: &mut RenderPipelineDescriptor,
layout: &MeshVertexBufferLayoutRef,
key: MaterialExtensionKey<Self>,
) -> Result<(), SpecializedMeshPipelineError> {
let growth = layout.0.get_layout(&[
ATTRIBUTE_GROWTH_ID.at_shader_location(8),
ATTRIBUTE_GROWTH_AXIS.at_shader_location(9),
ATTRIBUTE_GROWTH_OFFSET.at_shader_location(10),
])?;
descriptor.vertex.buffers[0].attributes.extend(growth.attributes);
specialize_flora(descriptor, layout, key.bind_group_data.leaf)
}
}
pub(crate) fn add_shaders(app: &mut App) {
bevy::shader::load_shader_library!(app, "growth_common.wesl");
bevy::asset::embedded_asset!(app, "growth.wesl");
bevy::asset::embedded_asset!(app, "growth_prepass.wesl");
}