wde_renderer/assets/
shader.rs

1use wde_logger::prelude::*;
2
3use bevy::{
4    asset::{AssetLoader, LoadContext, io::Reader},
5    prelude::*
6};
7use std::io::{Error, ErrorKind};
8use thiserror::Error;
9
10/// Stores a shader source as UTF-8 text. File should have a `.wgsl` extension.
11/// Most of the time, the user does not need to load shaders directly, as they can be embedded in materials and pipelines.
12/// Note: the shader will only be compiled on the GPU when used in a pipeline, so this is just a container for the source code.
13#[derive(Asset, TypePath, Clone, Debug)]
14pub struct Shader {
15    /// WGSL source contents as UTF-8 text.
16    pub content: String
17}
18
19#[derive(Debug, Error)]
20pub(crate) enum ShaderLoaderError {
21    #[error("Could not load shader: {0}")]
22    Io(#[from] std::io::Error)
23}
24#[derive(Default, TypePath)]
25pub(crate) struct ShaderLoader;
26impl AssetLoader for ShaderLoader {
27    type Asset = Shader;
28    type Settings = ();
29    type Error = ShaderLoaderError;
30
31    async fn load(
32        &self,
33        reader: &mut dyn Reader,
34        _settings: &Self::Settings,
35        load_context: &mut LoadContext<'_>
36    ) -> Result<Self::Asset, Self::Error> {
37        debug!("Loading shader {}.", load_context.path());
38
39        // Read the texture data
40        let mut bytes = Vec::new();
41        reader.read_to_end(&mut bytes).await?;
42
43        // Read the content
44        let content = match String::from_utf8(bytes) {
45            Ok(content) => content,
46            Err(_) => {
47                return Err(ShaderLoaderError::Io(Error::new(
48                    ErrorKind::InvalidData,
49                    "Could not convert shader to string."
50                )));
51            }
52        };
53        Ok(Shader { content })
54    }
55
56    fn extensions(&self) -> &[&str] {
57        &["wgsl"]
58    }
59}