pub use glin::macros::*;
pub use rin_util::WORKSPACE_DIR;
#[macro_export]
macro_rules! program_cache {
{ $vertex:expr, $fragment:expr } => {
thread_local!(static SHADER: ::std::cell::UnsafeCell<::std::collections::HashMap<usize, $crate::Program>> =
::std::cell::UnsafeCell::new(::std::collections::HashMap::new()));
pub fn get_program<'c, R: $crate::RenderSurface>(gl: &$crate::Renderer<'c, R>) -> &'static $crate::Program{
fn new_program<'c, R: $crate::RenderSurface>(gl: &$crate::Renderer<'c, R>) -> $crate::Program{
use rin_util::LogErr;
gl.new_program()
.from_src_bindings(&[
($crate::VERTEX_SHADER, shaders::VERTEX_SHADER),
($crate::FRAGMENT_SHADER, shaders::FRAGMENT_SHADER)
], $crate::default_attribute_bindings())
.log_err("Error loading program")
.unwrap()
}
SHADER.with(|cache| {
let cache = unsafe{ &mut *cache.get() };
let program = cache
.entry(gl.id())
.or_insert_with(|| new_program(gl));
unsafe{ ::std::mem::transmute(program) }
})
}
mod shaders{
pub static VERTEX_SHADER: &'static str = include_str!($vertex);
pub static FRAGMENT_SHADER: &'static str = include_str!($fragment);
}
};
{ $vertex:expr, $fragment:expr, $getter:ident, $shader:ident } => {
thread_local!(static $shader: ::std::cell::UnsafeCell<::std::collections::HashMap<usize, $crate::Program>> =
::std::cell::UnsafeCell::new(::std::collections::HashMap::new()));
pub fn $getter<'c, R: $crate::RenderSurface>(gl: &$crate::Renderer<'c, R>) -> &'static $crate::Program{
static VERTEX_SHADER: &'static str = include_str!($vertex);
static FRAGMENT_SHADER: &'static str = include_str!($fragment);
fn new_program<'c, R: $crate::RenderSurface>(gl: &$crate::Renderer<'c, R>) -> $crate::Program{
use rin_util::LogErr;
gl.new_program()
.from_src_bindings(&[
($crate::VERTEX_SHADER, VERTEX_SHADER),
($crate::FRAGMENT_SHADER, FRAGMENT_SHADER)
], $crate::default_attribute_bindings())
.log_err("Error loading program")
.unwrap()
}
$shader.with(|cache| {
let cache = unsafe{ &mut *cache.get() };
let program = cache
.entry(gl.id())
.or_insert_with(|| new_program(gl));
unsafe{ ::std::mem::transmute(program) }
})
}
};
{ $settings:expr, $getter:ident, $shader:ident } => {
thread_local!(static $shader: ::std::cell::UnsafeCell<::std::collections::HashMap<usize, $crate::Program>> =
::std::cell::UnsafeCell::new(::std::collections::HashMap::new()));
pub fn $getter<'c, R: $crate::RenderSurface>(gl: &$crate::Renderer<'c, R>) -> &'static $crate::Program{
fn new_program<'c, R: $crate::RenderSurface>(gl: &$crate::Renderer<'c, R>) -> $crate::Program{
use rin_util::LogErr;
gl.new_program()
.from_settings($settings)
.log_err("Error loading program")
.unwrap()
}
$shader.with(|cache| {
let cache = unsafe{ &mut *cache.get() };
let program = cache
.entry(gl.id())
.or_insert_with(|| new_program(gl));
unsafe{ ::std::mem::transmute(program) }
})
}
}
}
#[macro_export]
macro_rules! geometry_cache{
{$ty: ty, $mesh: expr} => {
thread_local!(static GEOMETRY: ::std::cell::UnsafeCell<::std::collections::HashMap<usize, $crate::SimpleVao<$ty>>> =
::std::cell::UnsafeCell::new(::std::collections::HashMap::new()));
pub fn get_geometry<'r, 'c, R: $crate::RenderSurface>(gl: &'r $crate::Renderer<'c, R>) -> &'r mut $crate::SimpleVao<$ty> {
GEOMETRY.with(|cache|{
let cache = unsafe{ &mut *cache.get() };
let vao = cache.entry(gl.id())
.or_insert_with(|| {
gl.new_simple_vao().from_data_bindings(
&$mesh,
$crate::default_attribute_bindings(),
$crate::gl::STATIC_DRAW).unwrap()
});
unsafe{ ::std::mem::transmute(vao) }
})
}
}
}
#[macro_export]
macro_rules! geometry_cache_per_vertex_type {
{} => {
thread_local!(static GEOMETRY: ::std::cell::UnsafeCell<::std::collections::HashMap<(usize, ::std::any::TypeId), Box<::std::any::Any>>> =
::std::cell::UnsafeCell::new(::std::collections::HashMap::new()));
pub fn get_geometry<'r, 'c, T: VertexFormat, R: $crate::offscreen_buffer::RenderSurface>(gl: &'r $crate::Renderer<'c, R>, mesh: ::graphics::Mesh<T>) -> &'r mut ::glin::SimpleVao<T> {
GEOMETRY.with(|cache|{
let cache = unsafe{ &mut *cache.get() };
let vao = cache.entry((gl.id(), ::std::any::TypeId::of::<T>()))
.or_insert_with(|| {
gl.new_simple_vao().from_data_bindings(
&$mesh,
&$crate::default_attribute_bindings(),
$crate::STATIC_DRAW).unwrap()
});
unsafe{ ::std::mem::transmute(vao) }
})
}
}
}
#[macro_export]
macro_rules! image_cache{
{$getter:ident, $cache_name: ident, $image: expr} => {
thread_local!(static $cache_name: ::std::cell::UnsafeCell<::std::collections::HashMap<usize, $crate::Texture>> =
::std::cell::UnsafeCell::new(::std::collections::HashMap::new()));
pub fn $getter<'r, 'c, R: $crate::RenderSurface>(gl: &'r $crate::Renderer<'c, R>) -> &'r mut $crate::Texture {
$cache_name.with(|cache|{
use rin_util::LogErr;
let cache = unsafe{ &mut *cache.get() };
let tex = cache.entry(gl.id())
.or_insert_with(|| {
gl.new_texture()
.from_image(&$image, $crate::TEXTURE_2D)
.log_err("Error loading image into texture")
.unwrap()
});
unsafe{ ::std::mem::transmute(tex) }
})
}
};
{$getter:ident, $cache_name: ident, $image: expr, $tex_init_fn: expr} => {
thread_local!(static $cache_name: ::std::cell::UnsafeCell<::std::collections::HashMap<usize, $crate::Texture>> =
::std::cell::UnsafeCell::new(::std::collections::HashMap::new()));
pub fn $getter<'r, 'c, R: $crate::RenderSurface>(gl: &'r $crate::Renderer<'c, R>) -> &'r mut $crate::Texture {
$cache_name.with(|cache|{
let cache = unsafe{ &mut *cache.get() };
let tex = cache.entry(gl.id())
.or_insert_with(|| {
let mut tex = gl.new_texture().from_image(&$image, $crate::TEXTURE_2D).unwrap();
$tex_init_fn(&mut tex);
tex
});
unsafe{ ::std::mem::transmute(tex) }
})
}
};
}
#[macro_export]
#[cfg(feature="glsl_debug")]
macro_rules! shader {
($ty: expr, $path: expr, $replacements: expr) => {{
let path = ::std::path::Path::new($path);
let base_path = if path.is_absolute(){
path.parent().map(|p| p.to_owned())
}else{
let src_path = ::std::path::Path::new(file!());
if src_path.is_absolute(){
src_path.parent().map(|p| p.to_owned())
}else{
$crate::macros::WORKSPACE_DIR
.join(std::path::Path::new(file!()))
.parent()
.map(|p| p.to_owned())
}
};
$crate::Shader::Path{
path: path.to_owned(),
replacements: $replacements,
base_path,
includes: Vec::new(),
ty: $ty,
}
}};
($ty: expr, $path: expr) => {{
$crate::shader!($ty, $path, vec![])
}};
}
#[macro_export]
#[cfg(not(feature="glsl_debug"))]
macro_rules! shader {
($ty: expr, $path: expr, $replacements: expr) => {{
let path = ::std::path::Path::new($path);
let base_path;
let absolute_path;
if path.is_absolute(){
base_path = path.parent().map(|p| p.to_owned());
absolute_path = path.to_owned();
}else{
base_path = $crate::macros::WORKSPACE_DIR
.join(std::path::Path::new(file!()))
.parent()
.map(|p| p.to_owned());
absolute_path = base_path
.as_ref()
.and_then(|b| b.join(path).canonicalize().ok())
.unwrap_or(path.to_owned());
};
$crate::Shader::Source{
include_name: absolute_path.to_str().unwrap().to_owned(),
source: include_str!($path).to_owned(),
replacements: $replacements,
base_path,
includes: Vec::new(),
ty: $ty,
}
}};
($ty: expr, $path: expr) => {{
$crate::shader!($ty, $path, vec![])
}};
}
#[macro_export]
macro_rules! vertex_shader {
($path: expr, $replacements: expr) => {
$crate::shader!($crate::VERTEX_SHADER, $path, $replacements)
};
($path: expr) => {
$crate::shader!($crate::VERTEX_SHADER, $path)
};
}
#[macro_export]
macro_rules! fragment_shader {
($path: expr, $replacements: expr) => {
$crate::shader!($crate::FRAGMENT_SHADER, $path, $replacements)
};
($path: expr) => {
$crate::shader!($crate::FRAGMENT_SHADER, $path)
};
}
#[macro_export]
macro_rules! shader_source {
($ty: expr, $source: expr) => {{
let include_name = match $ty{
gl::VERTEX_SHADER => format!("vertex shader inlined in {}:{}:{}", file!(), line!(), column!()),
gl::FRAGMENT_SHADER => format!("fragment_shader inlined in {}:{}:{}", file!(), line!(), column!()),
_ => panic!("Shader type not supported yet"),
};
$crate::renderer::Shader::Source{
include_name,
source: $source.to_owned(),
replacements: vec![],
base_path: None,
includes: Vec::new(),
ty: $ty,
}
}};
}
#[macro_export]
macro_rules! vertex_shader_source {
($source: expr) => {
$crate::shader_source!(crate::VERTEX_SHADER, $source)
};
}
#[macro_export]
macro_rules! fragment_shader_source {
($source: expr) => {
$crate::shader_source!(crate::FRAGMENT_SHADER, $source)
};
}