2021-32-bit-holiday-jam/src/shader_closure.rs

94 lines
1.8 KiB
Rust

use std::collections::*;
use std::iter::FromIterator;
use crate::{
renderable_model::AttrMap,
shader::ShaderProgram,
};
pub struct ShaderClosure {
program: ShaderProgram,
uniforms: HashMap <u32, i32>,
attributes: AttrMap,
}
pub struct BorrowedShaderVars <'a> {
pub unis: &'a HashMap <u32, i32>,
pub attrs: &'a AttrMap,
}
pub fn get_shader_attrs (
shader: &ShaderProgram,
attr_names: &[(usize, &str)]
)
-> AttrMap
{
let mut v = vec! [None; attr_names.iter ().map (|(i, _)| i).max ().unwrap () + 1];
let attrs = shader.get_attribute_locations (attr_names.iter ().map (|(_, v)| v).copied ());
for ((i, _), loc) in attr_names.iter ().zip (attrs.into_iter ()) {
v [*i] = loc;
}
v
}
pub fn get_shader_uniforms (
shader: &ShaderProgram,
uni_names: &[(u32, &str)]
)
-> HashMap <u32, i32>
{
let unis = shader.get_uniform_locations (uni_names.iter ().map (|(_, v)| v).copied ());
let pairs =
uni_names.iter ().map (|(i, _)| i).copied ()
.zip (unis.into_iter ())
.filter (|(_, v)| *v >= 0)
;
HashMap::from_iter (pairs)
}
impl ShaderClosure {
pub fn new (
program: ShaderProgram,
uniform_names: &[(u32, &str)],
attr_names: &[(usize, &str)]
) -> Self
{
let uniforms = get_shader_uniforms (&program, uniform_names);
let attributes = get_shader_attrs (&program, attr_names);
Self {
program,
uniforms,
attributes,
}
}
pub fn get_id (&self) -> u32 {
self.program.get_id ()
}
pub fn with <F> (&self, previous_id: Option <u32>, callback: F)
where F: Fn (BorrowedShaderVars)
{
if previous_id != Some (self.get_id ()) {
self.program.use_program ();
}
else {
//println! ("Elided use_program ()");
}
callback (BorrowedShaderVars {
unis: &self.uniforms,
attrs: &self.attributes,
});
}
}
pub trait ShaderLookup {
fn lookup <'a> (&'a self, id: u32) -> &'a ShaderClosure;
}