История изменений
Исправление KivApple, (текущая версия) :
Это загрузчик шейдеров. Идея в том, что для каждой шейдерной программы отдельная структура, которая помимо id шейдерной программы из OpenGL ещё хранит позиции всех uniform и attribute найденные при создании программы через glGetUniformLocation и glGetAttribLocation. Также все шейдерные программы реализуют трейт, который содержит new принимающий id шейдерной программы (на самом деле небольшую обёртку, у которой ещё есть Drop и некоторые другие методы актуальные для любой программы).
Идея в том, что можно вызвать метод загрузки, передав ему имена файлов вершинного и фрагментного шейдера, а также подставив через генерик нужный тип программы, а загрузчик либо вернёт уже загруженную программу, либо ещё загрузит и инициализирует (при этом вызывающему коду очень важно получить программу конкретного типа, ведь именно в программе конкретного типа будут лежать позиции нужных uniform и attribute именно для использования этой программы).
pub trait ShaderProgramWrapper {
fn new(program: ShaderProgram) -> Self where Self: Sized;
fn bind(&self) -> ShaderProgramBinding;
}
pub struct AssetLoader {
...
shader_programs: HashMap<(&'static str, &'static str, TypeId), Rc<dyn Any>>
...
}
impl AssetLoader {
pub fn load_shader_program<T: ShaderProgramWrapper + 'static>(
&mut self,
vertex_shader_file_name: &'static str,
fragment_shader_file_name: &'static str
) -> Rc<T> {
let key = (vertex_shader_file_name, fragment_shader_file_name, TypeId::of::<T>());
if let Some(program) = self.shader_programs.get(&key) {
program.clone().downcast().unwrap()
} else {
let program = Rc::new(T::new(ShaderProgram::new(&[
&self.load_vertex_shader(vertex_shader_file_name),
&self.load_fragment_shader(fragment_shader_file_name)
]).unwrap()));
self.shader_programs.insert(key, program.clone());
program
}
}
}
Решил проблему через Any.
Исправление KivApple, :
Это загрузчик шейдеров. Идея в том, что для каждой шейдерной программы отдельная структура, которая помимо id шейдерной программы из OpenGL ещё хранит позиции всех uniform и attribute найденные при создании программы через glGetUniformLocation и glGetAttribLocation. Также все шейдерные программы реализуют трейт, который содержит new принимающий id шейдерной программы (на самом деле небольшую обёртку, у которой ещё есть Drop и некоторые другие методы актуальные для любой программы).
Идея в том, что можно вызвать метод загрузки, передав ему имена файлов вершинного и фрагментного шейдера, а также подставив через генерик нужный тип программы, а загрузчик либо вернёт уже загруженную программу, либо ещё загрузит и инициализирует.
pub trait ShaderProgramWrapper {
fn new(program: ShaderProgram) -> Self where Self: Sized;
fn bind(&self) -> ShaderProgramBinding;
}
pub struct AssetLoader {
...
shader_programs: HashMap<(&'static str, &'static str, TypeId), Rc<dyn Any>>
...
}
impl AssetLoader {
pub fn load_shader_program<T: ShaderProgramWrapper + 'static>(
&mut self,
vertex_shader_file_name: &'static str,
fragment_shader_file_name: &'static str
) -> Rc<T> {
let key = (vertex_shader_file_name, fragment_shader_file_name, TypeId::of::<T>());
if let Some(program) = self.shader_programs.get(&key) {
program.clone().downcast().unwrap()
} else {
let program = Rc::new(T::new(ShaderProgram::new(&[
&self.load_vertex_shader(vertex_shader_file_name),
&self.load_fragment_shader(fragment_shader_file_name)
]).unwrap()));
self.shader_programs.insert(key, program.clone());
program
}
}
}
Решил проблему через Any.
Исходная версия KivApple, :
Это загрузчик шейдеров. Идея в том, что для каждой шейдерной программы отдельная структура, которая помимо id шейдерной программы из OpenGL ещё хранит позиции всех uniform и attribute найденные при создании программы через glGetUniformLocation и glGetAttributeLocation. Также все шейдерные программы реализуют трейт, который содержит new принимающий id шейдерной программы (на самом деле небольшую обёртку, у которой ещё есть Drop и некоторые другие методы актуальные для любой программы).
Идея в том, что можно вызвать метод загрузки, передав ему имена файлов вершинного и фрагментного шейдера, а также подставив через генерик нужный тип программы, а загрузчик либо вернёт уже загруженную программу, либо ещё загрузит и инициализирует.
pub trait ShaderProgramWrapper {
fn new(program: ShaderProgram) -> Self where Self: Sized;
fn bind(&self) -> ShaderProgramBinding;
}
pub struct AssetLoader {
...
shader_programs: HashMap<(&'static str, &'static str, TypeId), Rc<dyn Any>>
...
}
impl AssetLoader {
pub fn load_shader_program<T: ShaderProgramWrapper + 'static>(
&mut self,
vertex_shader_file_name: &'static str,
fragment_shader_file_name: &'static str
) -> Rc<T> {
let key = (vertex_shader_file_name, fragment_shader_file_name, TypeId::of::<T>());
if let Some(program) = self.shader_programs.get(&key) {
program.clone().downcast().unwrap()
} else {
let program = Rc::new(T::new(ShaderProgram::new(&[
&self.load_vertex_shader(vertex_shader_file_name),
&self.load_fragment_shader(fragment_shader_file_name)
]).unwrap()));
self.shader_programs.insert(key, program.clone());
program
}
}
}
Решил проблему через Any.