Index into sampler2D[] - 330 and below

Hey, so I’m using a sampler2D array for using multiple textures on my geometry. In GLSL 330 and below it turns out that we can’t use a variable to index into sampler2D arrays.

Does anybody have clever ideas or workarounds for this? I am perfectly willing to write another shader, I just would like to avoid some crazy if-else block if at all possible.

What is the length of your array? If it’s tiny, you can simply do N texture lookups and multiply all but the correct texture by zero.

You may also be able to use a GL_ARRAY_TEXTURE_2D, store all your textures in it and sample 1 layer from it - this can be an arbitrary layer, per fragment. Array textures have quite a few restrictions though, as all layers must have the same pixel format and dimensions.

I came across this some months ago so maybe my experience can help you.

It’s not that you can’t use a variable, but you can only use something that’s called an opaque type (https://www.opengl.org/wiki/Data_Type_(GLSL)#Opaque_types).

This means you can perfectly fine use uniforms. Depending on the way you implement your texture selection, you could use an int array to select the indices of your sampler array - does this work for you?

An alternative would be to use texture arrays. I finally did this because I got indices from a dynamic texture, so not opaque - but as mentioned by Riven, you there are limitations, for example all entries must have same size, format etc.

Maybe it’s ugly, but the if-else-thing would be possible too, of course. From my experience, there’s no speed penalty, but you would have a hardcoded max value for the index.

My array is size 16 and doing a for loop looks better, but sadly tends to perform worse for me than an if block. As far as opaque values go, when I’m batch rendering this won’t work. I could revert to a non-batch renderer when 400 isn’t supported, but that seems kind of pointless, we’ll see.

I’ll take a look at the GL_ARRAY_TEXTURE_2D, but this is really just to get one of my old computers rendering for testing more than actually supporting pre-330 (although technically I should support 330 :emo: ).

Thanks for the suggestions!

If you’re using OpenGL 3.3 already, just use GL_TEXTURE_ARRAY_2D. It’s really powerful and exactly for this use case.