geng
geng copied to clipboard
Uniform Arrays
NOT READY FOR MERGE!
One day I was doing glTF skinning (library for GENG soon) and I've noticed, that I can't pass an array of matrices as a transform for bones.
PR is ready for review. I've got a lot of problems with it, but it seems to be finally working (maybe it's just NVidia permissiveness). To use arrays in shader uniforms, you do:
uniform mat4 joints[100];
and
SingleUniform::new("joints[0]", vec![mat4::identity(); 100]); // This is the part where NVidia might just be a little to permissive...
For more information, see: https://gamedev.stackexchange.com/questions/157837/uniform-arrays-do-not-work-on-every-gpu https://stackoverflow.com/questions/37527264/glgetuniformlocation-get-elements-in-an-array-using-loop Quote from https://registry.khronos.org/OpenGL-Refpages/gl4/html/glGetUniformLocation.xhtml:
glGetUniformLocation returns an integer that represents the location of a specific uniform variable within a program object. name must be a null terminated string that contains no white space. name must be an active uniform variable name in program that is not a structure, an array of structures, or a subcomponent of a vector or a matrix. This function returns -1 if name does not correspond to an active uniform variable in program, if name starts with the reserved prefix "gl_", or if name is associated with an atomic counter or a named uniform block.
In case this doesn't work, the workaround is to make a custom ArrayUniform, would look something like this:
#[derive(Clone)]
pub struct ArrayUniform<'a, U: Uniform> {
name: &'a str,
values: Vec<U>, // You'll probably want a vector here, because uniform values can't be statically borrowed normally
}
impl<'a, U: Uniform> ArrayUniform<'a, U> {
pub fn new(name: &'a str, value: Vec<U>) -> Self {
Self {
name,
values: value,
}
}
}
impl<'a, U: Uniform> Uniforms for ArrayUniform<'a, U> {
fn walk_uniforms<C>(&self, visitor: &mut C)
where
C: UniformVisitor,
{
for (index, value) in self.values.iter().enumerate() {
visitor.visit(&format!("{}[{}]", self.name, index), &value);
}
}
}