3b/cl-opengl — Issue #32: gl:uniformfv is misleading, and gl:uniformiv is missing
Author: jacius
Created: 2011-11-14 05:29:37+00:00
State: open

The `gl:uniformfv` function name implies that it is a binding to `glUniform*fv` (meaning `glUniform1fv`, `glUniform2fv`, etc.) but instead it's just a kind of vector-destructuring wrapper around `gl:uniformf`. Also, `gl:uniformiv` is missing entirely. Without bindings to `glUniform*fv` and `glUniform*iv`, it is difficult to provide certain kinds of data to shaders.

My guess is that there has been a simple misunderstanding about what `glUniform*fv` does. It takes a float vector of an arbitrary length (not limited to 4), and treats it as an **array of vectors**. `glUniform1fv` treats it as an array of single floats, `glUniform2fv` treats it as an array of float pairs (i.e. vec2's), and so on.

So in C, if I wanted to use an array of 10 vec4's, I'd create an array with 40 floats in it, then call `glUniform4fv(location, 10, *my_array_of_40_floats)`. The first 4 items (0-3) in the array would form the first vec4, items 4-7 would form the second vec4, items 8-11 would form the third vec4, and so on, with items 36-39 forming the tenth/final vec4.

You can accomplish the same thing by querying OpenGL for the uniform location of the first element in the array, then calling `glUniform*f` with that location, then querying for the location of the second element in the array, then calling `glUniform*f` with that new location, and so on for every element in the array. But using `glUniform*fv` is much easier and more efficient. :-)

My recommendation is to document the current `gl:uniformfv` function as deprecated, to be removed at a later date. If you want to keep the "destructuring" wrapper around `gl:uniformf`, it should have a different name that won't be misleading.

Then, to add the missing functionality, I'd suggest adding `gl:uniform-fv` and `gl:uniform-iv`, each taking a sequence of sequences (e.g. `#(#(1 2) #(3 4) #(5 6))`, although lists would be allowed too). The length of the first inner sequence can be used to decide which `glUniform*fv` function to use, and the length of the outer sequence (i.e. the count of inner sequences) can be used for the "count" argument of `glUniform*fv`.

If that sounds good to you, I will be happy to write the code. Or, if you think it should have a more C-ish API (passing one long sequence, instead of nested sequences), we could do that instead.