geng icon indicating copy to clipboard operation
geng copied to clipboard

Uniform Arrays

Open InfiniteCoder01 opened this issue 1 year ago • 2 comments
trafficstars

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.

InfiniteCoder01 avatar Jan 09 '24 16:01 InfiniteCoder01

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.

InfiniteCoder01 avatar Jan 11 '24 17:01 InfiniteCoder01

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);
        }
    }
}

InfiniteCoder01 avatar Jan 11 '24 17:01 InfiniteCoder01