1use serde::{Deserialize, Serialize};
2use crate::logging::EnigmaMessage;
3use crate::smart_format;
4
5#[derive(Serialize, Deserialize, Clone)]
6pub struct ShaderSerializer {
7 fragment_shader: String,
8 vertex_shader: String,
9 geometry_shader: Option<String>
10}
11
12pub struct Shader {
13 pub fragment_shader: String,
14 pub vertex_shader: String,
15 pub geometry_shader: Option<String>
16}
17
18impl Shader {
19 pub fn new() -> Self {
20 Self {
21 fragment_shader: String::from(""),
22 vertex_shader: String::from(""),
23 geometry_shader: None,
24 }
25 }
26
27 pub fn from_serializer(serializer: ShaderSerializer) -> Self {
28 Self {
29 fragment_shader: serializer.fragment_shader,
30 vertex_shader: serializer.vertex_shader,
31 geometry_shader: serializer.geometry_shader,
32 }
33 }
34
35 pub fn to_serializer(&self) -> ShaderSerializer {
36 ShaderSerializer {
37 fragment_shader: self.fragment_shader.clone(),
38 vertex_shader: self.vertex_shader.clone(),
39 geometry_shader: self.geometry_shader.clone(),
40 }
41 }
42
43 pub fn set_fragment_shader(&mut self, fragment_shader: String) {
44 self.fragment_shader = fragment_shader;
45 }
46 pub fn set_vertex_shader(&mut self, vertex_shader: String) {
47 self.vertex_shader = vertex_shader;
48 }
49
50 pub fn set_geometry_shader(&mut self, geometry_shader: String) {
51 self.geometry_shader = Some(geometry_shader);
52 }
53
54 pub fn get_fragment_shader(&self) -> String {
55 self.fragment_shader.clone()
56 }
57 pub fn get_vertex_shader(&self) -> String {
58 self.vertex_shader.clone()
59 }
60
61 pub fn get_geometry_shader(&self) -> Option<String> {
62 self.geometry_shader.clone()
63 }
64
65 pub fn from_files(vertex_shader: &str, fragment_shader: &str, geometry_shader: Option<&str>) -> Self {
66 let vertex_shader = std::fs::read_to_string(vertex_shader).expect("Unable to read file");
67 let fragment_shader = std::fs::read_to_string(fragment_shader).expect("Unable to read file");
68 let geometry_shader = match geometry_shader {
69 Some(geometry_shader) => Some(std::fs::read_to_string(geometry_shader).expect("Unable to read file")),
70 None => None,
71 };
72 Self {
73 fragment_shader,
74 vertex_shader,
75 geometry_shader,
76 }
77 }
78
79 pub fn from_strings(vertex_shader: &str, fragment_shader: &str, geometry_shader: Option<&str>) -> Self {
80 Self {
81 fragment_shader: String::from(fragment_shader),
82 vertex_shader: String::from(vertex_shader),
83 geometry_shader: match geometry_shader {
84 Some(geometry_shader) => Some(String::from(geometry_shader)),
85 None => None,
86 },
87 }
88 }
89
90 pub fn log(&self) {
91 let mut logger = EnigmaMessage::new(Some(smart_format!("Vertex Shader:\n{}", self.vertex_shader).as_str()), true);
92 logger.extent(smart_format!("Fragment Shader:\n{}", self.fragment_shader).as_str());
93 match &self.geometry_shader {
94 Some(geometry_shader) => logger.extent(smart_format!("Geometry Shader:\n{}", geometry_shader).as_str()),
95 None => (),
96 }
97 logger.log();
98 }
99
100 pub fn default() -> Self {
101 let vertex_shader = r#"
102 #version 140
103 uniform float time;
104 uniform mat4 matrix;
105 in vec3 position;
106 void main() {
107 gl_Position = matrix * vec4(position, 1.0);
108 }
109 "#;
110
111 let fragment_shader = r#"
112 #version 140
113 uniform float time;
114 out vec4 color;
115 void main() {
116 color = vec4(1.0, 0.0, 1.0, 1.0);
117 }
118 "#;
119
120 Self {
121 fragment_shader: String::from(fragment_shader),
122 vertex_shader: String::from(vertex_shader),
123 geometry_shader: None,
124 }
125 }
126}
127
128impl Default for Shader {
129 fn default() -> Self {
130 Self::default()
131 }
132}
133
134impl std::fmt::Display for Shader {
135 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136 write!(f, "{}{}{}", self.vertex_shader, self.fragment_shader, match &self.geometry_shader {
137 Some(geometry_shader) => geometry_shader,
138 None => "",
139 })
140 }
141}
142
143impl std::fmt::Debug for Shader {
144 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145 write!(f, "{}{}{}", self.vertex_shader, self.fragment_shader, match &self.geometry_shader {
146 Some(geometry_shader) => geometry_shader,
147 None => "",
148 })
149 }
150}
151
152impl Clone for Shader {
153 fn clone(&self) -> Self {
154 Self {
155 fragment_shader: self.fragment_shader.clone(),
156 vertex_shader: self.vertex_shader.clone(),
157 geometry_shader: match &self.geometry_shader {
158 Some(geometry_shader) => Some(geometry_shader.clone()),
159 None => None,
160 },
161 }
162 }
163}