1use std::collections::HashMap;
2use std::ffi::CString;
3use std::fs::File;
4use std::io::Read;
5use std::ptr;
6use std::str;
7
8use gl;
9use gl::types::*;
10
11use cgmath::{Matrix, Matrix4, Vector3, Vector4};
12use cgmath::prelude::*;
13
14use bitflags::bitflags;
15use log::{warn, trace};
16
17pub struct Shader {
18 pub id: u32,
19 uniform_location_cache: HashMap<&'static str, i32>
20}
21
22impl Shader {
23 #[allow(dead_code)]
24 pub fn new(vertex_path: &str, fragment_path: &str, defines: &[String]) -> Shader {
25 let mut v_shader_file = File::open(vertex_path).unwrap_or_else(|_| panic!("Failed to open {}", vertex_path));
27 let mut f_shader_file = File::open(fragment_path).unwrap_or_else(|_| panic!("Failed to open {}", fragment_path));
28 let mut vertex_code = String::new();
29 let mut fragment_code = String::new();
30 v_shader_file
31 .read_to_string(&mut vertex_code)
32 .expect("Failed to read vertex shader");
33 f_shader_file
34 .read_to_string(&mut fragment_code)
35 .expect("Failed to read fragment shader");
36
37 Self::from_source(&vertex_code, &fragment_code, defines)
38 }
39
40 pub fn from_source(vertex_code: &str, fragment_code: &str, defines: &[String]) -> Shader {
41 let mut shader = Shader {
42 id: 0,
43 uniform_location_cache: HashMap::new()
44 };
45
46 let vertex_code = Self::add_defines(vertex_code, defines);
47 let v_shader_code = CString::new(vertex_code.as_bytes()).unwrap();
48 let fragment_code = Self::add_defines(fragment_code, defines);
49 let f_shader_code = CString::new(fragment_code.as_bytes()).unwrap();
50
51 unsafe {
53 let vertex = gl::CreateShader(gl::VERTEX_SHADER);
55 gl::ShaderSource(vertex, 1, &v_shader_code.as_ptr(), ptr::null());
56 gl::CompileShader(vertex);
57 shader.check_compile_errors(vertex, "VERTEX");
58 let fragment = gl::CreateShader(gl::FRAGMENT_SHADER);
60 gl::ShaderSource(fragment, 1, &f_shader_code.as_ptr(), ptr::null());
61 gl::CompileShader(fragment);
62 shader.check_compile_errors(fragment, "FRAGMENT");
63 let id = gl::CreateProgram();
65 gl::AttachShader(id, vertex);
66 gl::AttachShader(id, fragment);
67 gl::LinkProgram(id);
68 shader.check_compile_errors(id, "PROGRAM");
69 gl::DeleteShader(vertex);
71 gl::DeleteShader(fragment);
72 shader.id = id;
73 }
74
75 shader
76 }
77
78 fn add_defines(source: &str, defines: &[String]) -> String {
79 let defines = defines.iter()
82 .map(|define| format!("#define {}", define))
83 .collect::<Vec<_>>()
84 .join("\n");
85 let mut lines: Vec<_> = source.lines().collect();
86 if let Some(version_line) = lines.iter().position(|l| l.starts_with("#version")) {
87 lines.insert(version_line+1, &defines);
88 }
89 else {
90 lines.insert(0, &defines);
91 }
92 lines.join("\n")
93 }
94
95 pub unsafe fn use_program(&self) {
98 gl::UseProgram(self.id)
99 }
100
101 #[allow(dead_code)]
104 pub unsafe fn set_bool(&self, location: i32, value: bool) {
105 gl::Uniform1i(location, value as i32);
106 }
107 pub unsafe fn set_int(&self, location: i32, value: i32) {
109 gl::Uniform1i(location, value);
110 }
111 pub unsafe fn set_float(&self, location: i32, value: f32) {
113 gl::Uniform1f(location, value);
114 }
115 pub unsafe fn set_vector3(&self, location: i32, value: &Vector3<f32>) {
117 gl::Uniform3fv(location, 1, value.as_ptr());
118 }
119 pub unsafe fn set_vector4(&self, location: i32, value: &Vector4<f32>) {
121 gl::Uniform4fv(location, 1, value.as_ptr());
122 }
123 pub unsafe fn set_vec2(&self, location: i32, x: f32, y: f32) {
125 gl::Uniform2f(location, x, y);
126 }
127 pub unsafe fn set_vec3(&self, location: i32, x: f32, y: f32, z: f32) {
129 gl::Uniform3f(location, x, y, z);
130 }
131 pub unsafe fn set_mat4(&self, location: i32, mat: &Matrix4<f32>) {
133 gl::UniformMatrix4fv(location, 1, gl::FALSE, mat.as_ptr());
134 }
135
136 pub unsafe fn uniform_location(&mut self, name: &'static str) -> i32 {
138 if let Some(loc) = self.uniform_location_cache.get(name) {
139 return *loc;
140 }
141
142 let c_name = CString::new(name).unwrap();
143 let loc = gl::GetUniformLocation(self.id, c_name.as_ptr());
144 if loc == -1 {
145 trace!("uniform '{}' unknown for shader {}", name, self.id);
146 }
147 self.uniform_location_cache.insert(name, loc);
148 loc
149 }
150
151 unsafe fn check_compile_errors(&self, shader: u32, type_: &str) {
154 let mut success = i32::from(gl::FALSE);
155 let mut info_log = Vec::with_capacity(1024);
156 info_log.set_len(1024 - 1); if type_ != "PROGRAM" {
158 gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut success);
159 let log_type = if success == i32::from(gl::TRUE) { "WARNING" } else { "ERROR" };
160 let mut length = 0;
161 gl::GetShaderInfoLog(shader, 1024, &mut length, info_log.as_mut_ptr() as *mut GLchar);
162 if length == 0 { return }
163 panic!("{}::SHADER_COMPILATION_{} of type: {}\n{}",
164 log_type, log_type,
165 type_,
166 str::from_utf8(&info_log[0..length as usize]).unwrap());
167
168 } else {
169 gl::GetProgramiv(shader, gl::LINK_STATUS, &mut success);
170 let log_type = if success == i32::from(gl::TRUE) { "WARNING" } else { "ERROR" };
171 let mut length = 0;
172 gl::GetProgramInfoLog(shader, 1024, &mut length, info_log.as_mut_ptr() as *mut GLchar);
173 if length == 0 { return }
174 warn!("{}::PROGRAM_LINKING_{} of type: {}\n{}",
175 log_type, log_type,
176 type_,
177 str::from_utf8(&info_log[0..length as usize]).unwrap());
178 }
179
180 }
181}
182
183bitflags! {
184 pub struct ShaderFlags: u16 {
186 const HAS_NORMALS = 1;
188 const HAS_TANGENTS = 1 << 1;
189 const HAS_UV = 1 << 2;
190 const HAS_COLORS = 1 << 3;
191
192 const USE_IBL = 1 << 4;
194 const HAS_BASECOLORMAP = 1 << 5;
195 const HAS_NORMALMAP = 1 << 6;
196 const HAS_EMISSIVEMAP = 1 << 7;
197 const HAS_METALROUGHNESSMAP = 1 << 8;
198 const HAS_OCCLUSIONMAP = 1 << 9;
199 const USE_TEX_LOD = 1 << 10;
200 }
201}
202
203impl ShaderFlags {
204 pub fn as_strings(self) -> Vec<String> {
205 (0..15)
206 .map(|i| 1u16 << i)
207 .filter(|i| self.bits & i != 0)
208 .map(|i| format!("{:?}", ShaderFlags::from_bits_truncate(i)))
209 .collect()
210 }
211}
212
213#[allow(non_snake_case)]
214pub struct PbrUniformLocations {
215 pub u_MVPMatrix: i32,
218 pub u_ModelMatrix: i32,
219 pub u_Camera: i32,
220
221 pub u_LightDirection: i32,
222 pub u_LightColor: i32,
223
224 pub u_AmbientLightColor: i32,
225 pub u_AmbientLightIntensity: i32,
226
227 pub u_DiffuseEnvSampler: i32,
229 pub u_SpecularEnvSampler: i32,
230 pub u_brdfLUT: i32,
231
232 pub u_BaseColorSampler: i32,
235 pub u_BaseColorTexCoord: i32,
236 pub u_BaseColorFactor: i32,
237
238 pub u_NormalSampler: i32,
239 pub u_NormalTexCoord: i32,
240 pub u_NormalScale: i32,
241
242 pub u_EmissiveSampler: i32,
243 pub u_EmissiveTexCoord: i32,
244 pub u_EmissiveFactor: i32,
245
246 pub u_MetallicRoughnessSampler: i32,
247 pub u_MetallicRoughnessTexCoord: i32,
248 pub u_MetallicRoughnessValues: i32,
249
250 pub u_OcclusionSampler: i32,
251 pub u_OcclusionTexCoord: i32,
252 pub u_OcclusionStrength: i32,
253
254 pub u_AlphaBlend: i32,
255 pub u_AlphaCutoff: i32,
256
257 pub u_ScaleDiffBaseMR: i32,
260 pub u_ScaleFGDSpec: i32,
261 pub u_ScaleIBLAmbient: i32,
262}
263
264pub struct PbrShader {
265 pub shader: Shader,
266 pub flags: ShaderFlags,
267 pub uniforms: PbrUniformLocations,
268}
269
270impl PbrShader {
271 pub fn new(flags: ShaderFlags) -> Self {
272 let mut shader = Shader::from_source(
273 include_str!("shaders/pbr-vert.glsl"),
274 include_str!("shaders/pbr-frag.glsl"),
275 &flags.as_strings());
276
277 let uniforms = unsafe {
284 let uniforms = PbrUniformLocations {
285 u_MVPMatrix: shader.uniform_location("u_MVPMatrix"),
286 u_ModelMatrix: shader.uniform_location("u_ModelMatrix"),
287 u_Camera: shader.uniform_location("u_Camera"),
288
289 u_LightDirection: shader.uniform_location("u_LightDirection"),
290 u_LightColor: shader.uniform_location("u_LightColor"),
291
292 u_AmbientLightColor: shader.uniform_location("u_AmbientLightColor"),
293 u_AmbientLightIntensity: shader.uniform_location("u_AmbientLightIntensity"),
294
295 u_DiffuseEnvSampler: shader.uniform_location("u_DiffuseEnvSampler"),
296 u_SpecularEnvSampler: shader.uniform_location("u_SpecularEnvSampler"),
297 u_brdfLUT: shader.uniform_location("u_brdfLUT"),
298
299 u_BaseColorSampler: shader.uniform_location("u_BaseColorSampler"),
300 u_BaseColorTexCoord: shader.uniform_location("u_BaseColorTexCoord"),
301 u_BaseColorFactor: shader.uniform_location("u_BaseColorFactor"),
302
303 u_NormalSampler: shader.uniform_location("u_NormalSampler"),
304 u_NormalTexCoord: shader.uniform_location("u_NormalTexCoord"),
305 u_NormalScale: shader.uniform_location("u_NormalScale"),
306
307 u_EmissiveSampler: shader.uniform_location("u_EmissiveSampler"),
308 u_EmissiveTexCoord: shader.uniform_location("u_EmissiveTexCoord"),
309 u_EmissiveFactor: shader.uniform_location("u_EmissiveFactor"),
310
311 u_MetallicRoughnessSampler: shader.uniform_location("u_MetallicRoughnessSampler"),
312 u_MetallicRoughnessTexCoord: shader.uniform_location("u_MetallicRoughnessTexCoord"),
313 u_MetallicRoughnessValues: shader.uniform_location("u_MetallicRoughnessValues"),
314
315 u_OcclusionSampler: shader.uniform_location("u_OcclusionSampler"),
316 u_OcclusionTexCoord: shader.uniform_location("u_OcclusionTexCoord"),
317 u_OcclusionStrength: shader.uniform_location("u_OcclusionStrength"),
318
319 u_AlphaBlend: shader.uniform_location("u_AlphaBlend"),
320 u_AlphaCutoff: shader.uniform_location("u_AlphaCutoff"),
321
322 u_ScaleDiffBaseMR: shader.uniform_location("u_ScaleDiffBaseMR"),
323 u_ScaleFGDSpec: shader.uniform_location("u_ScaleFGDSpec"),
324 u_ScaleIBLAmbient: shader.uniform_location("u_ScaleIBLAmbient"),
325 };
326
327 shader.use_program();
328 shader.set_int(uniforms.u_BaseColorSampler, 0);
329 shader.set_int(uniforms.u_NormalSampler, 1);
330 shader.set_int(uniforms.u_EmissiveSampler, 2);
331 shader.set_int(uniforms.u_MetallicRoughnessSampler, 3);
332 shader.set_int(uniforms.u_OcclusionSampler, 4);
333
334 shader.set_vec3(uniforms.u_LightColor, 5.0, 5.0, 5.0);
335 shader.set_vec3(uniforms.u_LightDirection, 0.0, 0.5, 0.5);
337
338 shader.set_vec3(uniforms.u_AmbientLightColor, 1.0, 1.0, 1.0);
339 shader.set_float(uniforms.u_AmbientLightIntensity, 0.2);
340
341 uniforms
342 };
343
344 Self {
345 shader,
346 flags,
347 uniforms
348 }
349 }
350}