#[cfg(any(windows))]
use crate::windows::OpenGraphicsLibrary;
use core::mem::{
MaybeUninit,
transmute,
};
use std::ffi::CStr;
const FRAGMENT_SHADER:u32=0x8B30;
const VERTEX_SHADER:u32=0x8B31;
const GEOMETRY_SHADER :u32=0x8DD9;
const SHADER_TYPE:u32=0x8B4F;
const DELETE_STATUS:u32=0x8B80;
const COMPILE_STATUS:u32=0x8B81;
const INFO_LOG_LENGTH:u32=0x8B84;
const SHADER_SOURCE_LENGTH:u32=0x8B88;
#[repr(u32)]
#[derive(Clone,Copy,Debug)]
pub enum ShaderType{
FragmentShader=FRAGMENT_SHADER,
VertexShader=VERTEX_SHADER,
GeometryShader=GEOMETRY_SHADER,
}
#[repr(u32)]
#[derive(Clone,Copy,Debug)]
pub enum ShaderParameter{
ShaderType=SHADER_TYPE,
DeleteStatus=DELETE_STATUS,
CompileStatus=COMPILE_STATUS,
InfoLogLength=INFO_LOG_LENGTH,
ShaderSourceLength=SHADER_SOURCE_LENGTH,
}
pub struct Shader{
glCreateShader:usize,
glDeleteShader:usize,
glShaderSource:usize,
glCompileShader:usize,
glGetShaderiv:usize,
glGetShaderInfoLog:usize,
}
impl Shader{
pub const fn new()->Shader{
Self{
glCreateShader:0,
glDeleteShader:0,
glShaderSource:0,
glCompileShader:0,
glGetShaderiv:0,
glGetShaderInfoLog:0,
}
}
#[cfg(any(windows))]
pub fn load(&mut self,library:&OpenGraphicsLibrary){
unsafe{
self.glCreateShader=transmute(library.get_proc_address("glCreateShader\0"));
self.glDeleteShader=transmute(library.get_proc_address("glDeleteShader\0"));
self.glShaderSource=transmute(library.get_proc_address("glShaderSource\0"));
self.glCompileShader=transmute(library.get_proc_address("glCompileShader\0"));
self.glGetShaderiv=transmute(library.get_proc_address("glGetShaderiv\0"));
self.glGetShaderInfoLog=transmute(library.get_proc_address("glGetShaderInfoLog\0"));
}
}
}
impl Shader{
#[inline(always)]
pub fn create(&self,shader_type:ShaderType)->u32{
unsafe{
transmute::<usize,fn(ShaderType)->u32>(self.glCreateShader)(shader_type)
}
}
#[inline(always)]
pub unsafe fn delete(&self,shader:u32){
transmute::<usize,fn(u32)>(self.glDeleteShader)(shader)
}
#[inline(always)]
pub unsafe fn source(&self,shader:u32,source:&str){
let ptr=&source.as_ptr() as *const *const u8;
let length=&[source.bytes().len() as i32];
transmute::<usize,fn(u32,i32,*const*const u8,&i32)>(self.glShaderSource)(shader,1,ptr,&length[0])
}
#[inline(always)]
pub unsafe fn compile(&self,shader:u32){
transmute::<usize,fn(u32)>(self.glCompileShader)(shader)
}
#[inline(always)]
pub unsafe fn get_parameter(&self,shader:u32,parameter:ShaderParameter,value:&mut i32){
transmute::<usize,fn(u32,ShaderParameter,&mut i32)>(self.glGetShaderiv)(shader,parameter,value)
}
pub unsafe fn get_info_log(&self,shader:u32,log:&mut String){
let buffer=log.as_mut_vec();
let mut length:i32=MaybeUninit::uninit().assume_init();
transmute::<usize,fn(u32,i32,&mut i32,*mut u8)>(self.glGetShaderInfoLog)(
shader,
buffer.capacity() as i32,
&mut length,
buffer.as_mut_ptr()
);
if length!=0{
length-=1;
}
buffer.set_len(length as usize);
}
}