cl-opengl icon indicating copy to clipboard operation
cl-opengl copied to clipboard

gl:uniformfv is misleading, and gl:uniformiv is missing

Open jacius opened this issue 13 years ago • 2 comments

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.

jacius avatar Nov 14 '11 05:11 jacius

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.

jacius avatar Nov 14 '11 19:11 jacius

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.

3b avatar Dec 13 '11 22:12 3b