use glium::{Program, ProgramCreationError};
use sge_macros::gen_ref_type;
use sge_window::get_window_state;
macro_rules! include_program_internal {
($display: tt, $vertex: literal, $fragment: literal) => {{
let vertex_shader_src = include_str!($vertex);
let fragment_shader_src = include_str!($fragment);
Program::from_source($display, vertex_shader_src, fragment_shader_src, None)
.map(|p| SgeProgram { glium: p })
}};
}
#[macro_export]
macro_rules! include_program {
($vertex: literal, $fragment: literal) => {{
let vertex_shader_src = include_str!($vertex);
let fragment_shader_src = include_str!($fragment);
::sge::prelude::load_program(vertex_shader_src, fragment_shader_src)
}};
}
pub const FLAT_PROGRAM: ProgramRef = ProgramRef(0);
pub const CIRCLE_PROGRAM: ProgramRef = ProgramRef(1);
pub const TEXTURED_PROGRAM: ProgramRef = ProgramRef(2);
pub const FLAT_3D_PROGRAM: ProgramRef = ProgramRef(3);
pub const GOURAUD_3D_PROGRAM: ProgramRef = ProgramRef(4);
pub const TEXTURED_3D_PROGRAM: ProgramRef = ProgramRef(5);
pub const BLINN_PHONG_3D_PROGRAM: ProgramRef = ProgramRef(6);
pub const ROUNDED_PROGRAM: ProgramRef = ProgramRef(7);
pub const COPY_PROGRAM: ProgramRef = ProgramRef(8);
pub const RADIAL_PROGRAM: ProgramRef = ProgramRef(9);
pub struct SgeProgram {
glium: Program,
}
impl std::ops::Deref for SgeProgram {
type Target = Program;
fn deref(&self) -> &Self::Target {
&self.glium
}
}
impl std::ops::DerefMut for SgeProgram {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.glium
}
}
impl From<Program> for SgeProgram {
fn from(glium: Program) -> Self {
SgeProgram { glium }
}
}
impl From<SgeProgram> for Program {
fn from(program: SgeProgram) -> Self {
program.glium
}
}
gen_ref_type!(SgeProgram, ProgramRef, programs);
pub fn init() -> Result<(), ProgramCreationError> {
init_programs_storage();
let display = &get_window_state().display;
let storage = get_programs_state();
let program = include_program_internal!(
display,
"../shaders/flat/vertex.glsl",
"../shaders/flat/fragment.glsl"
)?;
storage.push(program);
let program = include_program_internal!(
display,
"../shaders/circle/vertex.glsl",
"../shaders/circle/fragment.glsl"
)?;
storage.push(program);
let program = include_program_internal!(
display,
"../shaders/sprite/vertex.glsl",
"../shaders/sprite/fragment.glsl"
)?;
storage.push(program);
let program = include_program_internal!(
display,
"../shaders/flat_3d/vertex.glsl",
"../shaders/flat_3d/fragment.glsl"
)?;
storage.push(program);
let program = include_program_internal!(
display,
"../shaders/gourad/vertex.glsl",
"../shaders/gourad/fragment.glsl"
)?;
storage.push(program);
let program = include_program_internal!(
display,
"../shaders/textured/vertex.glsl",
"../shaders/textured/fragment.glsl"
)?;
storage.push(program);
let program = include_program_internal!(
display,
"../shaders/blinn_phong/vertex.glsl",
"../shaders/blinn_phong/fragment.glsl"
)?;
storage.push(program);
let program = include_program_internal!(
display,
"../shaders/rounded/vertex.glsl",
"../shaders/rounded/fragment.glsl"
)?;
storage.push(program);
let program = include_program_internal!(
display,
"../shaders/copy/vertex.glsl",
"../shaders/copy/fragment.glsl"
)?;
storage.push(program);
let program = include_program_internal!(
display,
"../shaders/radial/vertex.glsl",
"../shaders/radial/fragment.glsl"
)?;
storage.push(program);
log::info!("Initialized shaders (programs)");
Ok(())
}
pub fn load_program(vertex: &str, fragment: &str) -> Result<ProgramRef, ProgramCreationError> {
let display = &get_window_state().display;
let sge: SgeProgram = Program::from_source(display, vertex, fragment, None)?.into();
Ok(sge.create())
}