basic linear algebra in gen?

metamax's icon

Forgive the beginner question but how do I apply a basic matrix transform inside of jit.gen/pix/gl.pix? I'm looking for the equivalent of mat() in GLSL. I don't see anything. With all of the convolution and matrix transforms throughout graphics and color management, there has to be something I'm missing. Every other shader I look at is full of transformation matrices.

While on the subject.. I wrote a .genexpr function to apply matrix transforms that I would like to use in codebox via require("");
I would also like change the coefficients dynamically by setting a parameter inside of the function. I am able to set the param with no problem when the code is in the patch but when called via require(""), it's lost. Setparam doesn't work either. Any thoughts? My patch is mess right now. I will post examples if needed.

Graham Wakefield's icon

There isn't currently the equivalent of GLSL matrix genTypes in jit.gen et al, but I've logged a feature request for it. It makes sense to have them!

And yes, if you can post (or PM me) an example -- as simplified as possible -- I can log a bug report on that too.

Graham

metamax's icon

Hi Graham, yes.. please log that request. Thanks. I'm very surprised that matrix transforms aren't already part of Gen. I think they will open a lot of doors.

In the meantime, I would like to create my own operators but as I look more closely, I can't seem to change *any* custom function parameters. So I think the fault is mine and not a bug.

I can get the following to work in [jit.pix] but not in [jit.gl.pix]. Not sure why. None of my attempts to insert a dynamic param into a function work. I just want to load custom functions via require and use them like any other operator in the gen objects.

Thanks for taking a look...

Max Patch
Copy patch and select New From Clipboard in Max.

metamax's icon

Graham, it appears to be more of a general bug with params inside of functions.. not just with params accessed via require().

All attempts to send values prepended with the name of a parameter inside a function generate error messages.

A workaround is to create a global param and equate it to the function param in the output argument.. and then prepend values with the global param name. When I do that, it works everywhere.. both in box and via require() from file.

Thanks again for looking into this.

Max Patch
Copy patch and select New From Clipboard in Max.

metamax's icon

To anyone else dealing with this issue, here is an example of changing functions params for a linear matrix operation.

Max Patch
Copy patch and select New From Clipboard in Max.

Graham Wakefield's icon

Hi,

Several points:

- Sending a message "offset 0." to the jit.gen will only work if there is a [param offset] at the top-level of the patcher, or a "Param offset" declared in a codebox at the top-level patcher. The param embedded in a function is not externally accessible in this way. It must be passed by argument one way or another. Here's a couple of ways it can be done:

func(v, offset, amp=1)    {
    return amp*(v+offset);
}
Param offset(0);
out1 = func(in1, offset, amp=0.5);
func(v, amp=1)    {
    Param off(0);
    return amp*(v+off);    
}
Param offset(0);
out1 = func(in1, off=offset, amp=0.5);

Note that embedding a Param inside a function like this is equivalent to putting it as an argument with assignment:

func(v, off=0, amp=1)    {
    return amp*(v+off);    
}
Param offset(0);
out1 = func(in1, off=offset, amp=0.5);

This is all consistent with the vignette documentation. The important thing to keep in mind is that a Param at the top level of a codebox is equivalent to a [param] in the patcher, whereas a Param embedded within a function is equivalent to a function argument addressed by name; they are somewhat different in nature.

---

In regard to your last example patcher, I figured out that you are doing a mat3x3 * vec4 operation, but the naming confused me for a moment (it's unfortunate that "matrix" has two meaning for Jitter already, but calling your function "matrix" and the Param "param" was a bit more confusing!) In this case the function doesn't actually need a Param -- you can just pass in the 3x3 matrix as an argument. I guess I might have written it like this (note that I reversed the argument order to match the multiplication order):

// apply a 3x3 matrix transform to a vec4
// input:         4-plane vector
// transform:     9-plane vector
// return:     4-plane vector
// i.e. return transform * input
mul_mat3x3(transform, input)    {
    return    vec( input.x*swiz(transform,0) + input.y*swiz(transform,1) + input.z*swiz(transform,2),
                  input.x*swiz(transform,3) + input.y*swiz(transform,4) + input.z*swiz(transform,5),
                  input.x*swiz(transform,6) + input.y*swiz(transform,7) + input.z*swiz(transform,8), 
                 input.w);
}

// example:
Param mn(1, 0, 0, 0, 1, 0, 0, 0, 1);
out1 = mul_mat3x3(mn, in1); 

Hope that helps!

metamax's icon

Graham, thanks. You know, I kinda feel bad for you.. but hey - you're the one who took the job programming for artists.

Okay, so I understand the function/param thing but I must say...... "top level" is as confusing as any terms I used. All attempts to set global params at the "top" of [codebox] fail with the error "declarations must come before any expressions". I now understand that 'top level' means outside of and after any function definitions but it was very confusing at first. None of the vignette examples of params declared within functions have any declared globals. As a beginner, I saw that functions had to be at the top of the code and assumed that params could be right there with them. fwiw, the term "main body" makes more sense than "top level", at least to me.

re: the matrix function.. I understand the confusion with the names I chose - but I do need to set the 9 matrix elements via param because I need to dynamically change those values via lists from outside of Gen. Concatenating 9-element vectors inside of gen every time I need to change values is not convenient. That's why I included the RGB to XYZ example in my last patch. Note how you can dynamically change illuminants from coll, etc. My use of vec4 is because jit.pix only seems to play ball with vec4 and I want something that passes alpha.

Thanks again for your time and help. You are a legend in these parts.
All the best.

Graham Wakefield's icon

Hi,

Yes I agree, "main body" is more accessible than "top-level". Aaargh terminology!

Max Patch
Copy patch and select New From Clipboard in Max.

What I was saying about the matrix function is that since you have a param in the main body, you don't need one in the function itself. Just pass in the param to the function as an argument. Your example will work without it, as below:

metamax's icon

^ Doh, of course. Even better! I misread your previous post. Thanks again, Graham.