Dairy-Drift/src/shader.rs

145 lines
6.1 KiB
Rust
Raw Normal View History

2023-03-06 10:13:01 +01:00
use glow::*;
use std::fs;
use std::ffi::{CString, CStr};
use std::str;
use cgmath::prelude::*;
/// Shader Struct for creating and using shaders in the Context of engine
///
2023-03-06 10:13:01 +01:00
pub struct shader<T: glow::HasContext> {
2023-03-06 10:13:01 +01:00
pub ID: T::Program,
}
2023-03-06 10:13:01 +01:00
impl shader<T>
{
/// Shader Constructor, will read, Compile and Create GLSL Program for use
///
/// # Example
/// `new(String::from("Example"))`
/// if the String given was "Example" the Program expects both shaders to be in the directory "resources/shaders/Example/"
/// with the vertex shader being called "shader.vert" and fragment "shader.frag"
2023-03-06 10:13:01 +01:00
pub fn new(path: &str, gl: glow::Context) -> shader<T>
{
//read file contents
let VERT_SHADER = fs::read_to_string(format!("resources/shaders/{path}/shader.vert")).unwrap();
2023-03-06 10:13:01 +01:00
let FRAG_SHADER = fs::read_to_string(format!("resources/shaders/{path}/shader.frag")).unwrap();
//create vertex shader
2023-03-06 10:13:01 +01:00
let vertex_shader = unsafe {gl.create_shader(glow::VERTEX_SHADER).unwrap() };
unsafe {
2023-03-06 10:13:01 +01:00
gl.shader_source(vertex_shader, &VERT_SHADER);
gl.compile_shader(vertex_shader);
2023-03-06 10:13:01 +01:00
}
// create fragment shader
let fragment_shader = unsafe{gl.create_shader(glow::FRAGMENT_SHADER).unwrap()};
unsafe {
gl.shader_source(fragment_shader, &FRAG_SHADER);
gl.compile_shader(fragment_shader);
if !gl.get_shader_compile_status(fragment_shader) {
panic!("Error, Compiling Fragment Shader: {}", gl.get_shader_info_log(fragment_shader));
}
2023-03-06 10:13:01 +01:00
let shader_program = gl.create_program().unwrap();
2023-03-06 10:13:01 +01:00
gl.attach_shader(shader_program, vertex_shader);
gl.attach_shader(shader_program, fragment_shader);
gl.link_program(shader_program);
if !gl.get_program_link_status(shader_program) {
panic!("Error, Linking Shader Program {}", gl.get_program_info_log(shader_program));
}
2023-03-06 10:13:01 +01:00
gl.detach_shader(shader_program, vertex_shader);
gl.detach_shader(shader_program, fragment_shader);
gl.delete_shader(vertex_shader);
gl.delete_shader(fragment_shader);
2023-03-06 10:13:01 +01:00
shader {
ID: shader_program,
};
}
}
2023-03-06 10:13:01 +01:00
// return program
/// uses Shader
pub fn Use(&self)
{
unsafe {gl::UseProgram(self.ID);}
}
// BOILERPLATE JUMPSCARE
pub fn setBool(&self, name: &CStr, value: bool )
{unsafe {gl::Uniform1i(gl::GetUniformLocation(self.ID, name.as_ptr()), value as i32);}}
pub fn setInt(&self, name: &CStr, value: u32 )
{unsafe {gl::Uniform1i(gl::GetUniformLocation(self.ID, name.as_ptr()), value as i32);}}
pub fn setFloat(&self, name: &CStr, value: f32 )
{unsafe {gl::Uniform1f(gl::GetUniformLocation(self.ID, name.as_ptr()), value as f32);}}
pub fn setVec2(&self, name: &CStr, value: &cgmath::Vector2<f32> )
{unsafe {gl::Uniform2fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, value.as_ptr());}}
pub fn setVector2d(&self, name: &CStr, x: f32, y: f32)
{unsafe {gl::Uniform2f(gl::GetUniformLocation(self.ID, name.as_ptr()), x, y);}}
pub fn setVector3(&self, name: &CStr, value: cgmath::Vector3<f32> )
{unsafe {gl::Uniform3fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, value.as_ptr());}}
pub fn setVector3d(&self, name: &CStr, x: f32, y: f32, z: f32 )
{unsafe {gl::Uniform3f(gl::GetUniformLocation(self.ID, name.as_ptr()), x, y, z);}}
pub fn setVector4(&self, name: &CStr, value: &cgmath::Vector4<f32> )
{unsafe {gl::Uniform4fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, value.as_ptr());}}
pub fn setVector4d(&self, name: &CStr, x: f32, y: f32, z: f32, w: f32)
{unsafe {gl::Uniform4f(gl::GetUniformLocation(self.ID, name.as_ptr()), x, y, z, w);}}
pub fn setMat2(&self, name: &CStr, value: &cgmath::Matrix2<f32>)
{unsafe {gl::UniformMatrix2fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, gl::FALSE, value.as_ptr());}}
pub fn setMat3(&self, name: &CStr, value: &cgmath::Matrix3<f32>)
{unsafe {gl::UniformMatrix3fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, gl::FALSE, value.as_ptr());}}
pub fn setMat4(&self, name: &CStr, value: &cgmath::Matrix4<f32>)
{unsafe {gl::UniformMatrix4fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, gl::FALSE, value.as_ptr());}}
2023-03-06 10:13:01 +01:00
}
#[cfg(test)]
mod tests {
use glfw;
use glfw::Context;
use gl;
use super::*;
#[test]
fn ShaderLoading() {
// initialize GLFW
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
// set window hints
glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
glfw.window_hint(glfw::WindowHint::Resizable(false));
//create Window
let (mut window, events) = glfw.create_window(480, 320, "Shader Test", glfw::WindowMode::Windowed).unwrap();
let (screen_width, screen_height) = window.get_framebuffer_size();
// setup window
window.make_current();
window.set_key_polling(true);
// initialize gl
gl::load_with(|ptr| window.get_proc_address(ptr) as *const _);
let Shader = shader::new("basic");
Shader.Use();
}
}