cl-opengl
cl-opengl copied to clipboard
gl:uniformfv is misleading, and gl:uniformiv is missing
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.
While I was sleeping last night, my brain realized that we could salvage the existing gl:uniformfv
without breaking backwards compatibility. In C, glUniform*fv
can be used as a destructuring version of glUniform*f
, if the count arg is 1 and the float array only has enough values for 1 vector. So in Lisp, we could treat a single, non-nested sequence as a special case, equivalent to a sequence with one inner sequence, i.e. #(1 2 3)
would have the same effect as #(#(1 2 3))
. That would allow existing calls to gl:uniformfv
to still work, while also providing a proper binding to glUniform*fv
for future code to use.
Hmm, hard to say which would be a better API. Nested sequences is probably easier to use, not sure I like guessing the function by just looking at one of the inner sequences though.
Maybe just keep the count in the name (gl:uniform4fv
etc.) for the multiple uniform versions? Then they could handle nested sequences or flat vectors, without having to guess.