LINUX.ORG.RU

История изменений

Исправление 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.