use gl;
use glin::{self, Result};
#[cfg(any(feature="gl", feature="gles"))]
use glin::texture::Swizzles;
use glin::SurfaceCreationContext;
use super::{CreationProxy, default_attribute_bindings};
use na::{pnt2, convert, Pnt2};
use math::Rect;
use glin::CreationContext as GlinCreationContext;
use std::borrow::{Borrow, BorrowMut};
use std::mem;
use rect_packer::DensePacker;
pub struct GenericShadowMap {
depth_buffer: glin::Fbo,
depth_program: glin::Program,
shadow_sampler: glin::Sampler,
debug_draw_sampler: glin::Sampler,
settings: Settings,
}
#[derive(Clone, Copy, Debug)]
pub struct Settings{
pub size: u16,
pub frustum_size: f32,
pub near_clip: f32,
pub far_clip: f32,
pub bias: f32,
}
pub struct Builder(pub(crate) CreationProxy);
impl Builder{
pub fn create_generic(self, settings: Settings, resolution: glin::fbo::DepthFormat) -> Result<GenericShadowMap>{
let depth_texture = self.0.new_fbo_depth_attachment().texture(settings.size as u32, settings.size as u32, resolution)?;
let mut fbo = self.0.new_fbo().from_depth(depth_texture)?;
{
let fbo_tex = fbo.depth_tex_mut().unwrap();
#[cfg(any(feature="gl", feature="gles"))]
fbo_tex.set_swizzles(Swizzles::r_to_rgb());
fbo_tex.set_min_mag_filters(gl::NEAREST, gl::NEAREST);
fbo_tex.set_wrap_s(gl::CLAMP_TO_EDGE);
fbo_tex.set_wrap_t(gl::CLAMP_TO_EDGE);
}
let mut debug_draw_sampler = self.0.new_sampler();
debug_draw_sampler.set_min_mag_filters(gl::NEAREST, gl::NEAREST);
debug_draw_sampler.set_wrap_s(gl::CLAMP_TO_EDGE);
debug_draw_sampler.set_wrap_t(gl::CLAMP_TO_EDGE);
debug_draw_sampler.set_compare_mode(gl::NONE);
let mut shadow_sampler = self.0.new_sampler();
shadow_sampler.set_min_mag_filters(gl::NEAREST, gl::NEAREST);
shadow_sampler.set_wrap_s(gl::CLAMP_TO_EDGE);
shadow_sampler.set_wrap_t(gl::CLAMP_TO_EDGE);
shadow_sampler.set_compare_mode(gl::COMPARE_REF_TO_TEXTURE);
shadow_sampler.set_compare_func(gl::LEQUAL);
let program_settings = glin::program::Settings{
version: ::gl::default_glsl_version(),
precission: glin::program::ShaderPrecision::High,
extensions: vec![],
defines: vec![],
bindings: default_attribute_bindings(),
shaders: vec![
(gl::VERTEX_SHADER, include_str!("shaders/depth.vs.glsl")),
(gl::FRAGMENT_SHADER, include_str!("shaders/depth.fs.glsl")),
],
.. Default::default()
};
let depth_program = self.0.new_program()
.from_settings(program_settings)?;
Ok(GenericShadowMap{
depth_buffer: fbo,
depth_program,
settings,
debug_draw_sampler,
shadow_sampler,
})
}
fn create_mega(self, size: u32, resolution: glin::fbo::DepthFormat) -> Result<MegaShadowMap>{
let max_texture_size = self.0.capabilities().max_texture_size;
let num_textures_required = (size as f32 / max_texture_size as f32).round() as u32;
let texture_size = if max_texture_size >= size { size } else { max_texture_size };
let mut depth_buffers = (0..num_textures_required).map(|_| {
let depth_texture = self.0
.new_fbo_depth_attachment()
.texture(texture_size as u32, texture_size as u32, resolution)
.unwrap();
self.0.new_fbo().from_depth(depth_texture).unwrap()
}).collect::<Vec<_>>();
let occupancy_map = (0..num_textures_required).map(|_|{
DensePacker::new(texture_size as i32, texture_size as i32)
}).collect();
for fbo in depth_buffers.iter_mut() {
let fbo_tex = fbo.depth_tex_mut().unwrap();
#[cfg(any(feature="gl", feature="gles"))]
fbo_tex.set_swizzles(Swizzles::r_to_rgb());
fbo_tex.set_min_mag_filters(gl::NEAREST, gl::NEAREST);
fbo_tex.set_wrap_s(gl::CLAMP_TO_EDGE);
fbo_tex.set_wrap_t(gl::CLAMP_TO_EDGE);
}
let mut debug_draw_sampler = self.0.new_sampler();
debug_draw_sampler.set_min_mag_filters(gl::NEAREST, gl::NEAREST);
debug_draw_sampler.set_wrap_s(gl::CLAMP_TO_EDGE);
debug_draw_sampler.set_wrap_t(gl::CLAMP_TO_EDGE);
debug_draw_sampler.set_compare_mode(gl::NONE);
let mut shadow_sampler = self.0.new_sampler();
shadow_sampler.set_min_mag_filters(gl::NEAREST, gl::NEAREST);
shadow_sampler.set_wrap_s(gl::CLAMP_TO_EDGE);
shadow_sampler.set_wrap_t(gl::CLAMP_TO_EDGE);
shadow_sampler.set_compare_mode(gl::COMPARE_REF_TO_TEXTURE);
shadow_sampler.set_compare_func(gl::LEQUAL);
let program_settings = glin::program::Settings{
version: ::gl::default_glsl_version(),
precission: glin::program::ShaderPrecision::High,
extensions: vec![],
defines: vec![],
bindings: default_attribute_bindings(),
shaders: vec![
(gl::VERTEX_SHADER, include_str!("shaders/depth.vs.glsl")),
(gl::FRAGMENT_SHADER, include_str!("shaders/depth.fs.glsl")),
],
.. Default::default()
};
let depth_program = self.0.new_program()
.from_settings(program_settings)?;
Ok(MegaShadowMap{
depth_buffers,
depth_program,
debug_draw_sampler,
shadow_sampler,
occupancy_map,
})
}
pub fn create_pcss(self, settings: Settings, resolution: glin::fbo::DepthFormat) -> Result<PCSS>{
self.create_generic(settings, resolution).map(|shadow_map|
PCSS{
shadow_map,
})
}
pub fn create_poisson(self, settings: Settings, resolution: glin::fbo::DepthFormat) -> Result<Poisson>{
self.create_generic(settings, resolution).map(|shadow_map|
Poisson{
shadow_map,
shadow_sub: 0.9,
soft_scatter: 300.
})
}
pub fn create_hard(self, settings: Settings, resolution: glin::fbo::DepthFormat) -> Result<Hard>{
self.create_generic(settings, resolution).map(|shadow_map|
Hard{
shadow_map,
})
}
pub fn create_gaussian(self, settings: Settings, resolution: glin::fbo::DepthFormat) -> Result<Gaussian>{
self.create_generic(settings, resolution).map(|shadow_map|
Gaussian{
shadow_map,
})
}
}
impl GenericShadowMap{
pub fn debug_draw_sampler(&self) -> glin::TextureSampler{
self.depth_buffer.depth_tex().unwrap().texture_sampler(&self.debug_draw_sampler)
}
pub fn shadow_sampler(&self) -> glin::TextureSampler{
self.depth_buffer.depth_tex().unwrap().texture_sampler(&self.shadow_sampler)
}
pub fn fbo(&self) -> &glin::Fbo{
&self.depth_buffer
}
pub fn fbo_mut(&mut self) -> &mut glin::Fbo{
&mut self.depth_buffer
}
pub fn program(&self) -> &glin::Program{
&self.depth_program
}
pub fn frustum_size(&self) -> f32{
self.settings.frustum_size
}
pub fn near_clip(&self) -> f32{
self.settings.near_clip
}
pub fn far_clip(&self) -> f32{
self.settings.far_clip
}
pub fn viewport(&self) -> Rect<i32> {
Rect{pos: pnt2(0, 0), width: self.fbo().width() as i32, height: self.fbo().height() as i32}
}
pub fn bias(&self) -> f32{
self.settings.bias
}
pub fn set_bias(&mut self, bias: f32){
self.settings.bias = bias
}
}
struct MegaShadowMap{
depth_buffers: Vec<glin::Fbo>,
depth_program: glin::Program,
shadow_sampler: glin::Sampler,
debug_draw_sampler: glin::Sampler,
occupancy_map: Vec<DensePacker>,
}
impl MegaShadowMap{
pub fn find_free_space(&mut self, size: u16) -> Option<(usize, Pnt2<u32>)>{
for (map_idx, map) in self.occupancy_map.iter_mut().enumerate(){
if let Some(rect) = map.pack(size as i32, size as i32, false){
return Some((map_idx, pnt2(rect.x as u32, rect.y as u32)))
}
}
None
}
pub fn view(&mut self, settings: Settings) -> Option<MegaShadowMapView<&MegaShadowMap>>{
self.find_free_space(settings.size).map(move |(index, pos)|{
MegaShadowMapView{
shadow_map: self as &MegaShadowMap,
index: index as i32,
x: pos.x,
y: pos.y,
settings,
}
})
}
}
struct MegaShadowMapView<S: Borrow<MegaShadowMap>> {
shadow_map: S,
index: i32,
x: u32,
y: u32,
settings: Settings
}
pub trait ShadowMapView{
fn uniforms(&self) -> Vec<glin::program::Uniform>;
fn debug_draw_sampler(&self) -> glin::TextureSampler;
fn shadow_sampler(&self) -> glin::TextureSampler;
fn fbo(&self) -> &glin::Fbo;
fn program(&self) -> &glin::Program;
fn frustum_size(&self) -> f32;
fn near_clip(&self) -> f32;
fn far_clip(&self) -> f32;
fn bias(&self) -> f32;
fn viewport(&self) -> Rect<i32>;
fn shadow_sampler_idx(&self) -> i32;
}
impl <S: Borrow<MegaShadowMap>> ShadowMapView for MegaShadowMapView<S>{
fn uniforms(&self) -> Vec<glin::program::Uniform>{
let shadow_map = glin::program::uniform(&format!("shadow_map[{}]", self.index), &(self.debug_draw_sampler(), gl::TextureBindingPoints::Shadow1 as u32 + self.index as u32 * 2));
let shadow_map_pcf = glin::program::uniform(&format!("shadow_map_pcf[{}]", self.index), &(self.shadow_sampler(), gl::TextureBindingPoints::Shadow2 as u32 + self.index as u32 * 2));
vec![
shadow_map,
shadow_map_pcf,
]
}
fn debug_draw_sampler(&self) -> glin::TextureSampler{
self.fbo().depth_tex().unwrap().texture_sampler(&self.shadow_map.borrow().debug_draw_sampler)
}
fn shadow_sampler(&self) -> glin::TextureSampler{
self.fbo().depth_tex().unwrap().texture_sampler(&self.shadow_map.borrow().shadow_sampler)
}
fn fbo(&self) -> &glin::Fbo{
&self.shadow_map.borrow().depth_buffers[self.index as usize]
}
fn program(&self) -> &glin::Program{
&self.shadow_map.borrow().depth_program
}
fn frustum_size(&self) -> f32{
self.settings.frustum_size
}
fn near_clip(&self) -> f32{
self.settings.near_clip
}
fn far_clip(&self) -> f32{
self.settings.far_clip
}
fn bias(&self) -> f32{
self.settings.bias
}
fn viewport(&self) -> Rect<i32>{
Rect{pos: pnt2(self.x as i32, self.y as i32), width: self.settings.size as i32, height: self.settings.size as i32}
}
fn shadow_sampler_idx(&self) -> i32{
self.index
}
}
impl<S: Borrow<GenericShadowMap>> ShadowMapView for S {
fn uniforms(&self) -> Vec<glin::program::Uniform>{
let shadow_map = glin::program::uniform(&format!("shadow_map[{}]", 0), &(self.debug_draw_sampler(), gl::TextureBindingPoints::Shadow1 as u32));
let shadow_map_pcf = glin::program::uniform(&format!("shadow_map_pcf[{}]", 0), &(self.shadow_sampler(), gl::TextureBindingPoints::Shadow2 as u32));
vec![
shadow_map,
shadow_map_pcf,
]
}
fn debug_draw_sampler(&self) -> glin::TextureSampler{
self.fbo().depth_tex().unwrap().texture_sampler(&self.borrow().debug_draw_sampler)
}
fn shadow_sampler(&self) -> glin::TextureSampler{
self.fbo().depth_tex().unwrap().texture_sampler(&self.borrow().shadow_sampler)
}
fn fbo(&self) -> &glin::Fbo{
&self.borrow().depth_buffer
}
fn program(&self) -> &glin::Program{
&self.borrow().depth_program
}
fn frustum_size(&self) -> f32{
self.borrow().settings.frustum_size
}
fn near_clip(&self) -> f32{
self.borrow().settings.near_clip
}
fn far_clip(&self) -> f32{
self.borrow().settings.far_clip
}
fn bias(&self) -> f32{
self.borrow().settings.bias
}
fn viewport(&self) -> Rect<i32>{
Rect{pos: pnt2(0, 0), width: self.borrow().settings.size as i32, height: self.borrow().settings.size as i32}
}
fn shadow_sampler_idx(&self) -> i32{
0
}
}
impl<S: Borrow<GenericShadowMap>> ShadowMapView for (S, i32) {
fn uniforms(&self) -> Vec<glin::program::Uniform>{
let shadow_map = glin::program::uniform(&format!("shadow_map[{}]", self.1), &(self.debug_draw_sampler(), gl::TextureBindingPoints::Shadow1 as u32 + self.1 as u32 * 2));
let shadow_map_pcf = glin::program::uniform(&format!("shadow_map_pcf[{}]", self.1), &(self.shadow_sampler(), gl::TextureBindingPoints::Shadow2 as u32 + self.1 as u32 * 2));
vec![
shadow_map,
shadow_map_pcf,
]
}
fn debug_draw_sampler(&self) -> glin::TextureSampler{
self.fbo().depth_tex().unwrap().texture_sampler(&self.0.borrow().debug_draw_sampler)
}
fn shadow_sampler(&self) -> glin::TextureSampler{
self.fbo().depth_tex().unwrap().texture_sampler(&self.0.borrow().shadow_sampler)
}
fn fbo(&self) -> &glin::Fbo{
&self.0.borrow().depth_buffer
}
fn program(&self) -> &glin::Program{
&self.0.borrow().depth_program
}
fn frustum_size(&self) -> f32{
self.0.borrow().settings.frustum_size
}
fn near_clip(&self) -> f32{
self.0.borrow().settings.near_clip
}
fn far_clip(&self) -> f32{
self.0.borrow().settings.far_clip
}
fn bias(&self) -> f32{
self.0.borrow().settings.bias
}
fn viewport(&self) -> Rect<i32>{
Rect{pos: pnt2(0, 0), width: self.0.borrow().settings.size as i32, height: self.0.borrow().settings.size as i32}
}
fn shadow_sampler_idx(&self) -> i32{
self.1
}
}
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub enum Type{
PCSS,
Poisson,
Gaussian,
Hard,
}
pub struct PCSS<S = GenericShadowMap>{
shadow_map: S,
}
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)]
pub struct PCSSData{
near: f32,
far: f32,
frustum_size: f32,
bias: f32,
viewport: Rect<f32>,
shadow_map_idx: i32,
padding: [f32;3],
}
impl<S: ShadowMapView> PCSS<S>{
pub fn debug_draw_sampler(&self) -> glin::TextureSampler{
self.shadow_map.borrow().debug_draw_sampler()
}
pub fn shadow_sampler(&self) -> glin::TextureSampler{
self.shadow_map.borrow().shadow_sampler()
}
pub fn fbo(&self) -> &glin::Fbo{
self.shadow_map.borrow().fbo()
}
pub fn program(&self) -> &glin::Program{
self.shadow_map.borrow().program()
}
pub fn frustum_size(&self) -> f32{
self.shadow_map.borrow().frustum_size()
}
pub fn near_clip(&self) -> f32{
self.shadow_map.borrow().near_clip()
}
pub fn far_clip(&self) -> f32{
self.shadow_map.borrow().far_clip()
}
pub fn viewport(&self) -> Rect<i32> {
self.shadow_map.borrow().viewport()
}
pub fn bias(&self) -> f32{
self.shadow_map.borrow().bias()
}
pub fn data(&self) -> PCSSData{
PCSSData{
near: self.near_clip(),
far: self.far_clip(),
frustum_size: self.frustum_size(),
bias: self.bias(),
viewport: convert(self.shadow_map.borrow().viewport()),
shadow_map_idx: self.shadow_map.borrow().shadow_sampler_idx(),
padding: unsafe{ mem::uninitialized() },
}
}
}
impl<S: BorrowMut<GenericShadowMap>> PCSS<S>{
pub fn fbo_mut(&mut self) -> &mut glin::Fbo{
self.shadow_map.borrow_mut().fbo_mut()
}
pub fn set_bias(&mut self, bias: f32){
self.shadow_map.borrow_mut().set_bias(bias)
}
}
pub struct Poisson<S = GenericShadowMap>{
shadow_map: S,
shadow_sub: f32,
soft_scatter: f32,
}
#[allow(dead_code)]
pub struct PoissonData{
near: f32,
far: f32,
frustum_size: f32,
bias: f32,
viewport: Rect<f32>,
shadow_map_idx: i32,
shadow_sub: f32,
soft_scatter: f32,
padding: f32,
}
impl<S: ShadowMapView> Poisson<S>{
pub fn debug_draw_sampler(&self) -> glin::TextureSampler{
self.shadow_map.borrow().debug_draw_sampler()
}
pub fn shadow_sampler(&self) -> glin::TextureSampler{
self.shadow_map.borrow().shadow_sampler()
}
pub fn fbo(&self) -> &glin::Fbo{
self.shadow_map.borrow().fbo()
}
pub fn program(&self) -> &glin::Program{
self.shadow_map.borrow().program()
}
pub fn frustum_size(&self) -> f32{
self.shadow_map.borrow().frustum_size()
}
pub fn near_clip(&self) -> f32{
self.shadow_map.borrow().near_clip()
}
pub fn far_clip(&self) -> f32{
self.shadow_map.borrow().far_clip()
}
pub fn viewport(&self) -> Rect<i32> {
self.shadow_map.borrow().viewport()
}
pub fn bias(&self) -> f32{
self.shadow_map.borrow().bias()
}
pub fn shadow_sub(&self) -> f32{
self.shadow_sub
}
pub fn soft_scatter(&self) -> f32{
self.soft_scatter
}
pub fn set_shadow_sub(&mut self, shadow_sub: f32){
self.shadow_sub = shadow_sub
}
pub fn set_soft_scatter(&mut self, soft_scatter: f32){
self.soft_scatter = soft_scatter
}
pub fn data(&self) -> PoissonData{
PoissonData{
near: self.near_clip(),
far: self.far_clip(),
frustum_size: self.frustum_size(),
bias: self.bias(),
shadow_sub: self.shadow_sub(),
soft_scatter: self.soft_scatter(),
viewport: convert(self.shadow_map.borrow().viewport()),
shadow_map_idx: self.shadow_map.borrow().shadow_sampler_idx(),
padding: unsafe{ mem::uninitialized() },
}
}
}
impl<S: BorrowMut<GenericShadowMap>> Poisson<S>{
pub fn fbo_mut(&mut self) -> &mut glin::Fbo{
self.shadow_map.borrow_mut().fbo_mut()
}
pub fn set_bias(&mut self, bias: f32){
self.shadow_map.borrow_mut().set_bias(bias)
}
}
pub struct Hard<S = GenericShadowMap>{
shadow_map: S,
}
#[allow(dead_code)]
pub struct HardData{
near: f32,
far: f32,
frustum_size: f32,
bias: f32,
viewport: Rect<f32>,
shadow_map_idx: i32,
padding: [f32;3],
}
impl<S: ShadowMapView> Hard<S>{
pub fn debug_draw_sampler(&self) -> glin::TextureSampler{
self.shadow_map.borrow().debug_draw_sampler()
}
pub fn shadow_sampler(&self) -> glin::TextureSampler{
self.shadow_map.borrow().shadow_sampler()
}
pub fn fbo(&self) -> &glin::Fbo{
self.shadow_map.borrow().fbo()
}
pub fn program(&self) -> &glin::Program{
self.shadow_map.borrow().program()
}
pub fn frustum_size(&self) -> f32{
self.shadow_map.borrow().frustum_size()
}
pub fn near_clip(&self) -> f32{
self.shadow_map.borrow().near_clip()
}
pub fn far_clip(&self) -> f32{
self.shadow_map.borrow().far_clip()
}
pub fn viewport(&self) -> Rect<i32> {
self.shadow_map.borrow().viewport()
}
pub fn bias(&self) -> f32{
self.shadow_map.borrow().bias()
}
pub fn data(&self) -> HardData{
HardData{
near: self.near_clip(),
far: self.far_clip(),
frustum_size: self.frustum_size(),
bias: self.bias(),
viewport: convert(self.shadow_map.borrow().viewport()),
shadow_map_idx: self.shadow_map.borrow().shadow_sampler_idx(),
padding: unsafe{ mem::uninitialized() },
}
}
}
impl<S: BorrowMut<GenericShadowMap>> Hard<S>{
pub fn fbo_mut(&mut self) -> &mut glin::Fbo{
self.shadow_map.borrow_mut().fbo_mut()
}
pub fn set_bias(&mut self, bias: f32){
self.shadow_map.borrow_mut().set_bias(bias)
}
}
pub struct Gaussian<S = GenericShadowMap>{
shadow_map: S,
}
#[allow(dead_code)]
pub struct GaussianData{
near: f32,
far: f32,
frustum_size: f32,
bias: f32,
viewport: Rect<f32>,
shadow_map_idx: i32,
padding: [f32;3],
}
impl<S: ShadowMapView> Gaussian<S>{
pub fn debug_draw_sampler(&self) -> glin::TextureSampler{
self.shadow_map.borrow().debug_draw_sampler()
}
pub fn shadow_sampler(&self) -> glin::TextureSampler{
self.shadow_map.borrow().shadow_sampler()
}
pub fn fbo(&self) -> &glin::Fbo{
self.shadow_map.borrow().fbo()
}
pub fn program(&self) -> &glin::Program{
self.shadow_map.borrow().program()
}
pub fn frustum_size(&self) -> f32{
self.shadow_map.borrow().frustum_size()
}
pub fn near_clip(&self) -> f32{
self.shadow_map.borrow().near_clip()
}
pub fn far_clip(&self) -> f32{
self.shadow_map.borrow().far_clip()
}
pub fn viewport(&self) -> Rect<i32> {
self.shadow_map.borrow().viewport()
}
pub fn bias(&self) -> f32{
self.shadow_map.borrow().bias()
}
pub fn data(&self) -> GaussianData{
GaussianData{
near: self.near_clip(),
far: self.far_clip(),
frustum_size: self.frustum_size(),
bias: self.bias(),
viewport: convert(self.shadow_map.borrow().viewport()),
shadow_map_idx: self.shadow_map.borrow().shadow_sampler_idx(),
padding: unsafe{ mem::uninitialized() },
}
}
}
impl<S: BorrowMut<GenericShadowMap>> Gaussian<S>{
pub fn fbo_mut(&mut self) -> &mut glin::Fbo{
self.shadow_map.borrow_mut().fbo_mut()
}
pub fn set_bias(&mut self, bias: f32){
self.shadow_map.borrow_mut().set_bias(bias)
}
}
pub trait ShadowMap{
fn uniforms(&self, shadow_map_index: usize) -> Vec<glin::program::Uniform>;
fn non_ubo_uniforms(&self, shadow_map_index: usize) -> Vec<glin::program::Uniform>;
fn fbo(&self) -> &glin::Fbo;
fn program(&self) -> &glin::Program;
fn frustum_size(&self) -> f32;
fn near_clip(&self) -> f32;
fn far_clip(&self) -> f32;
fn viewport(&self) -> Rect<i32>;
fn bias(&self) -> f32;
fn shadow_map_type(&self) -> &'static str;
fn shadow_sampler(&self) -> &dyn ShadowMapView;
}
impl<S: ShadowMapView> ShadowMap for PCSS<S>{
fn uniforms(&self, shadow_map_index: usize) -> Vec<glin::program::Uniform>{
let shadow_map = glin::program::uniform(&format!("shadow_map[{}]", shadow_map_index),
&(self.debug_draw_sampler(),
gl::TextureBindingPoints::Shadow1 as u32 + shadow_map_index as u32 * 2));
let shadow_map_pcf = glin::program::uniform(&format!("shadow_map_pcf[{}]", shadow_map_index),
&(self.shadow_sampler(),
gl::TextureBindingPoints::Shadow2 as u32 + shadow_map_index as u32 * 2));
vec![
shadow_map,
shadow_map_pcf,
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_near", shadow_map_index),
&self.shadow_map.borrow().near_clip()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_far", shadow_map_index),
&self.shadow_map.borrow().far_clip()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_frustum_size", shadow_map_index),
&self.shadow_map.borrow().frustum_size()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_bias", shadow_map_index),
&self.shadow_map.borrow().bias()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_idx", shadow_map_index),
&(shadow_map_index as i32)),
]
}
fn non_ubo_uniforms(&self, shadow_map_index: usize) -> Vec<glin::program::Uniform>{
let shadow_map = glin::program::uniform(&format!("shadow_map[{}]", shadow_map_index),
&(self.debug_draw_sampler(),
gl::TextureBindingPoints::Shadow1 as u32 + shadow_map_index as u32 * 2));
let shadow_map_pcf = glin::program::uniform(&format!("shadow_map_pcf[{}]", shadow_map_index),
&(self.shadow_sampler(),
gl::TextureBindingPoints::Shadow2 as u32 + shadow_map_index as u32 * 2));
vec![
shadow_map,
shadow_map_pcf,
]
}
fn fbo(&self) -> &glin::Fbo{
self.shadow_map.borrow().fbo()
}
fn program(&self) -> &glin::Program{
self.shadow_map.borrow().program()
}
fn frustum_size(&self) -> f32{
self.shadow_map.borrow().frustum_size()
}
fn near_clip(&self) -> f32{
self.shadow_map.borrow().near_clip()
}
fn far_clip(&self) -> f32{
self.shadow_map.borrow().far_clip()
}
fn viewport(&self) -> Rect<i32> {
self.shadow_map.borrow().viewport()
}
fn bias(&self) -> f32{
self.shadow_map.borrow().bias()
}
fn shadow_map_type(&self) -> &'static str{
"SHADOW_MAP_PCSS"
}
fn shadow_sampler(&self) -> &dyn ShadowMapView{
self.shadow_map.borrow()
}
}
impl<S: ShadowMapView> ShadowMap for Poisson<S>{
fn uniforms(&self, shadow_map_index: usize) -> Vec<glin::program::Uniform>{
let shadow_map_pcf = glin::program::uniform(&format!("shadow_map_pcf[{}]", shadow_map_index),
&(self.shadow_sampler(),
gl::TextureBindingPoints::Shadow1 as u32 + shadow_map_index as u32));
vec![
shadow_map_pcf,
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_near", shadow_map_index),
&self.shadow_map.borrow().near_clip()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_far", shadow_map_index),
&self.shadow_map.borrow().far_clip()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_frustum_size", shadow_map_index),
&self.shadow_map.borrow().frustum_size()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_bias", shadow_map_index),
&self.shadow_map.borrow().bias()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_sub", shadow_map_index),
&(self.shadow_sub as i32)),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_soft_scatter", shadow_map_index),
&(self.soft_scatter as i32)),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_idx", shadow_map_index),
&(shadow_map_index as i32)),
]
}
fn non_ubo_uniforms(&self, shadow_map_index: usize) -> Vec<glin::program::Uniform>{
let shadow_map_pcf = glin::program::uniform(&format!("shadow_map_pcf[{}]", shadow_map_index),
&(self.shadow_sampler(),
gl::TextureBindingPoints::Shadow1 as u32 + shadow_map_index as u32));
vec![
shadow_map_pcf,
]
}
fn fbo(&self) -> &glin::Fbo{
self.shadow_map.borrow().fbo()
}
fn program(&self) -> &glin::Program{
self.shadow_map.borrow().program()
}
fn frustum_size(&self) -> f32{
self.shadow_map.borrow().frustum_size()
}
fn near_clip(&self) -> f32{
self.shadow_map.borrow().near_clip()
}
fn far_clip(&self) -> f32{
self.shadow_map.borrow().far_clip()
}
fn viewport(&self) -> Rect<i32> {
self.shadow_map.borrow().viewport()
}
fn bias(&self) -> f32{
self.shadow_map.borrow().bias()
}
fn shadow_map_type(&self) -> &'static str{
"SHADOW_MAP_POISON_DISK"
}
fn shadow_sampler(&self) -> &dyn ShadowMapView{
self.shadow_map.borrow()
}
}
impl<S: ShadowMapView> ShadowMap for Hard<S>{
fn uniforms(&self, shadow_map_index: usize) -> Vec<glin::program::Uniform>{
let shadow_map_pcf = glin::program::uniform(&format!("shadow_map_pcf[{}]", shadow_map_index),
&(self.shadow_sampler(),
gl::TextureBindingPoints::Shadow1 as u32));
vec![
shadow_map_pcf,
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_near", shadow_map_index),
&self.shadow_map.borrow().near_clip()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_far", shadow_map_index),
&self.shadow_map.borrow().far_clip()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_frustum_size", shadow_map_index),
&self.shadow_map.borrow().frustum_size()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_bias", shadow_map_index),
&self.shadow_map.borrow().bias()),
]
}
fn non_ubo_uniforms(&self, shadow_map_index: usize) -> Vec<glin::program::Uniform>{
let shadow_map_pcf = glin::program::uniform(&format!("shadow_map_pcf[{}]", shadow_map_index),
&(self.shadow_sampler(),
gl::TextureBindingPoints::Shadow1 as u32 + shadow_map_index as u32));
vec![
shadow_map_pcf,
]
}
fn fbo(&self) -> &glin::Fbo{
self.shadow_map.borrow().fbo()
}
fn program(&self) -> &glin::Program{
self.shadow_map.borrow().program()
}
fn frustum_size(&self) -> f32{
self.shadow_map.borrow().frustum_size()
}
fn near_clip(&self) -> f32{
self.shadow_map.borrow().near_clip()
}
fn far_clip(&self) -> f32{
self.shadow_map.borrow().far_clip()
}
fn viewport(&self) -> Rect<i32> {
self.shadow_map.borrow().viewport()
}
fn bias(&self) -> f32{
self.shadow_map.borrow().bias()
}
fn shadow_map_type(&self) -> &'static str{
"SHADOW_MAP_HARD"
}
fn shadow_sampler(&self) -> &dyn ShadowMapView{
self.shadow_map.borrow()
}
}
impl<S: ShadowMapView> ShadowMap for Gaussian<S>{
fn uniforms(&self, shadow_map_index: usize) -> Vec<glin::program::Uniform>{
let shadow_map_pcf = glin::program::uniform(&format!("shadow_map_pcf[{}]", shadow_map_index),
&(self.shadow_sampler(),
gl::TextureBindingPoints::Shadow1 as u32 + shadow_map_index as u32));
vec![
shadow_map_pcf,
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_near", shadow_map_index),
&self.shadow_map.borrow().near_clip()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_far", shadow_map_index),
&self.shadow_map.borrow().far_clip()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_map_frustum_size", shadow_map_index),
&self.shadow_map.borrow().frustum_size()),
glin::program::uniform(
&format!("shadow_maps[{}].shadow_bias", shadow_map_index),
&self.shadow_map.borrow().bias()),
]
}
fn non_ubo_uniforms(&self, shadow_map_index: usize) -> Vec<glin::program::Uniform>{
let shadow_map_pcf = glin::program::uniform(&format!("shadow_map_pcf[{}]", shadow_map_index),
&(self.shadow_sampler(),
gl::TextureBindingPoints::Shadow1 as u32 + shadow_map_index as u32));
vec![
shadow_map_pcf,
]
}
fn fbo(&self) -> &glin::Fbo{
self.shadow_map.borrow().fbo()
}
fn program(&self) -> &glin::Program{
self.shadow_map.borrow().program()
}
fn frustum_size(&self) -> f32{
self.shadow_map.borrow().frustum_size()
}
fn near_clip(&self) -> f32{
self.shadow_map.borrow().near_clip()
}
fn far_clip(&self) -> f32{
self.shadow_map.borrow().far_clip()
}
fn viewport(&self) -> Rect<i32> {
self.shadow_map.borrow().viewport()
}
fn bias(&self) -> f32{
self.shadow_map.borrow().bias()
}
fn shadow_map_type(&self) -> &'static str{
"SHADOW_MAP_GAUSSIAN"
}
fn shadow_sampler(&self) -> &dyn ShadowMapView{
self.shadow_map.borrow()
}
}
impl<S: ShadowMapView> From<S> for PCSS<S>{
fn from(shadow_map: S) -> PCSS<S>{
PCSS{
shadow_map
}
}
}
impl<S: ShadowMapView> From<S> for Poisson<S>{
fn from(shadow_map: S) -> Poisson<S>{
Poisson{
shadow_map,
shadow_sub: 0.9,
soft_scatter: 300.
}
}
}
impl<S: ShadowMapView> From<S> for Hard<S>{
fn from(shadow_map: S) -> Hard<S>{
Hard{
shadow_map,
}
}
}
impl<S: ShadowMapView> From<S> for Gaussian<S>{
fn from(shadow_map: S) -> Gaussian<S>{
Gaussian{
shadow_map,
}
}
}
pub trait DirectionalShadowMap<S = GenericShadowMap>: ShadowMap + From<S>{}
impl<S: ShadowMapView> DirectionalShadowMap<S> for PCSS<S>{}
impl<S: ShadowMapView> DirectionalShadowMap<S> for Poisson<S>{}
impl<S: ShadowMapView> DirectionalShadowMap<S> for Gaussian<S>{}
impl<S: ShadowMapView> DirectionalShadowMap<S> for Hard<S>{}
pub trait SpotShadowMap<S = GenericShadowMap>: ShadowMap + From<S>{}
impl<S: ShadowMapView> SpotShadowMap<S> for PCSS<S>{}
impl<S: ShadowMapView> SpotShadowMap<S> for Poisson<S>{}
impl<S: ShadowMapView> SpotShadowMap<S> for Gaussian<S>{}
impl<S: ShadowMapView> SpotShadowMap<S> for Hard<S>{}