1use data;
4use util;
5
6use std::{io, ops, str};
7use std::borrow::Borrow;
8use std::path::Path;
9
10#[derive(Clone, Debug, PartialEq, Eq, Hash)]
12pub struct Source(pub(crate) String);
13
14impl ops::Deref for Source {
15 type Target = [u8];
16 fn deref(&self) -> &Self::Target {
17 self.0.as_bytes()
18 }
19}
20
21impl Source {
22 fn preprocess<P: AsRef<Path>>(
23 root: P,
24 code: &str,
25 ) -> io::Result<String> {
26 let root = root.as_ref();
27 let mut new_code = String::new();
28 for line in code.lines() {
29 if line.starts_with("#include") {
30 if let Some(arg) = line.split_whitespace().skip(1).next() {
31 if arg.starts_with('<') {
32 if let Some(pos) = arg[1 ..].find('>') {
33 let name = &arg[1 .. (pos + 1)];
34 let path = format!("data/shaders/{}.glsl", name);
35 let content = &data::FILES.get(&path).unwrap();
36 new_code += str::from_utf8(content.borrow()).unwrap();
37 }
38 } else if arg.starts_with('"') {
39 if let Some(pos) = arg[1 ..].find('"') {
40 let relative_path = &arg[1 .. (pos + 1)];
41 let path = root.join(relative_path);
42 let content = util::read_file_to_string(&path)?;
43 let include = Self::preprocess(root, &content)?;
44 new_code += &include;
45 }
46 }
47 }
48 } else {
49 new_code.push_str(&line);
50 new_code.push('\n');
51 }
52 }
53 Ok(new_code)
54 }
55
56 pub fn default(
58 name: &str,
59 suffix: &str,
60 ) -> io::Result<Self> {
61 let path = format!("data/shaders/{}_{}.glsl", name, suffix);
62 let unprocessed = data::FILES.get(&path).unwrap();
63 let processed = Self::preprocess("", str::from_utf8(unprocessed.borrow()).unwrap())?;
64 Ok(Source(processed))
65 }
66
67 pub fn user<P: AsRef<Path>>(
69 root: P,
70 name: &str,
71 suffix: &str,
72 ) -> io::Result<Self> {
73 let base_name = format!("{}_{}.glsl", name, suffix);
74 let path = root.as_ref().join(&base_name);
75 let unprocessed = util::read_file_to_string(Path::new(&path))?;
76 let processed = Self::preprocess(root, &unprocessed)?;
77 Ok(Source(processed))
78 }
79}
80
81macro_rules! decl_shaders {
82 { $(($pso:ident, $doc:ident, $ty:ident),)* } => {
83 $( decl_shaders!($pso, $doc, $ty); )*
84
85 #[derive(Clone, Debug, Default)]
87 pub struct Set {
88 $(
89 #[allow(missing_docs)]
90 pub $pso: $ty,
91 )*
92 }
93 };
94
95 ($pso:ident, $doc:ident, $ty:ident) => {
96 #[allow(missing_docs)]
97 #[derive(Clone, Debug)]
98 pub struct $ty {
99 pub(crate) vs: Source,
101
102 pub(crate) ps: Source,
104 }
105
106 impl $ty {
107 pub fn user<P: AsRef<Path>>(root: P) -> io::Result<Self> {
109 Ok(Self {
110 vs: Source::user(&root, stringify!($pso), "vs")?,
111 ps: Source::user(&root, stringify!($pso), "ps")?,
112 })
113 }
114 }
115
116 impl Default for $ty {
117 fn default() -> Self {
118 Self {
119 vs: Source::default(stringify!($pso), "vs").unwrap(),
120 ps: Source::default(stringify!($pso), "ps").unwrap(),
121 }
122 }
123 }
124 };
125}
126
127decl_shaders! {
128 (basic, basic, Basic),
129 (gouraud, Gouraud, Gouraud),
130 (pbr, PBR, Pbr),
131 (phong, Phong, Phong),
132 (quad, quad, Quad),
133 (shadow, shadow, Shadow),
134 (skybox, skybox, Skybox),
135 (sprite, sprite, Sprite),
136}