Closed raymoo closed 7 years ago
It seems like this is implemented by GLSL compilers as loop unrolling: https://stackoverflow.com/questions/19868781/glsl-indexing-into-uniform-array-with-variable-length
So I guess it would make sense that this isn't possible. I will need to write instances for vector of 100 uniforms I guess.
Hi! No unfortunately that is not currently supported in GPipe.
The workaround is to use 1d textures instead. You would then have to represent your light data as primitive types, but you should be able to abstract away the sample functions and return a data type of your choice instead.
@tobbebex: That sounds like a good workaround, I'll try it out.
EDIT: Actually I think I will just read in a static number of uniforms and use that (using ifThenElse
and friends to ignore the ones that aren't filled). My uniform includes light space projection matrices and would require lots of samples per iteration. I think this will be similar to how vanilla GLSL does looping over a uniform buffer.
I tried doing what I said I would do in the edit, and for large numbers I get an error from declaring too many uniform blocks. It looks like each access to the uniform buffer gets compiled to a separate uniform block rather than the uniform being declared as an array and accesses being made through that. Is that right? Is there something that is in the way of making it use arrays? (I don't know much GLSL)
Maybe this is why you suggested using textures.
I would suggest looking up deferred shading. It s a common solution to the complexity problem of multiple lights.
I will consider it, but my project deadline is soon and am okay with the limitation of only a few lights if I can get more things implemented. I'm also worried about increasing the number of draw calls too much.
I'm guessing I would render the scene once for each light and add the colors together in a final pass by summing samples from an array texture?
In deferred shading you render geometry like normal, but instead of writing a lit color to the frame buffer you write positions, normals and material parameters (like surface color, roughness, etc) to a g-buffer. You then render every light using this g-buffer and adds the results. Just google it.
I guess you could write a UniformInput instance for lists, hardcoding it to read in 100 elements (serialize the length first, then "take 100" of the list, padded with zeroes if shorter than 100)...
I didn't end up deferring lighting calculations, though I did have to write out some geometry info because I wanted to implement SSAO. Next time I need to do something like this I'll take the lists as uniform inputs approach. If I had more time on my project I would have just switched completely to deferred rendering.
What I didn't really get while I was having problems was that GPipe uniforms are associated with GLSL uniform blocks, rather than GLSL uniforms. I think it would help if the documentation indicated that uniform collections meant to all be available at once should be grouped into one element of a uniform buffer rather than spread across one individually.
Please make a pull request for that documentation change if you like. I think the types expresses it already: getUniform gets the index in the uniform buffer from the shader environment as an Int (and not from the actual shader as an S a Int)
In OpenGL 3.3 you can only refer to uniform arrays with static indices, so if you want to index one in a loop you have to either unroll it or do n if statements for each possible value of the loop counter. I think that sometimes the GLSL compiler will unroll loops for you. I thought that the Int type was expressing this restriction (it is the same restriction, but uniform arrays have it too).
Hi, I'm looking for a way to loop through a list of uniforms (for example, light sources) in the shader, but I can't find one. I can't use
while
to do the looping becausegetUniform
operates in aShader
monad.Is there some way that I can do this?
EDIT: To clarify, by "list of uniforms" I mean a bunch of stuff in a uniform buffer.