Implementing Texture Arrays

Can anyone tell me if there is a problem with the code below? The shaders result is only solid black. Possibly an incomplete texture?


int _width = 2;
int _height = 2;
GLubyte texels[16] =
{
    0,   0,   0,   255,
    255, 0,   0,   255,
    0,   255, 0,   255,
    0,   0,   255, 255,
};




glUseProgram(shader->program);


GLuint _buffer;
glGenTextures(1, &_buffer);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, _buffer);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, _width, _height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, _width, _height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texels);

Fragment shader snippet;


#version 420


layout (binding = 0) uniform sampler2DArray arrayMap;

void main(void){
outcolor = texture(arrayMap, vec3(ex_texcoords0.x,ex_texcoords0.y,0));

I’m implementing this with a game engine but would just like to know if the above is the correct way of creating and reading texture arrays. That will tell me if the problem exists within the engine itself. Thank you.

Did you remember to change the minification filter? The default is GL_NEAREST_MIPMAP_LINEAR, which won’t work (sampling returns zeros) if you don’t create all of the mipmap levels.

I hadn’t changed it. I added this line below glTexSubImage3D() but still no success. Is this the way to turn mipmaps off?

glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

If commands such as these are used later within the engine could that cause issues? Can I unbind the textures or something so no future command influences them?

[QUOTE=SpiderPig500;1292459]I hadn’t changed it. I added this line below glTexSubImage3D() but still no success. Is this the way to turn mipmaps off?

glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

[/QUOTE]

If the texture is bound to the active texture unit as the GL_TEXTURE_2D_ARRAY target, yes, this disables use of MIPmaps by normal texture sampling.

If commands such as these are used later within the engine could that cause issues?

If that texture is still bound, yes. You need to be deliberate about what API calls you make and which objects are bound when you make them.

Can I unbind the textures or something so no future command influences them?

You can, but this potentially reduces your performance. So I would only use this if performance isn’t critical or you are just debugging.

Binding 0 to that texture target on that texture unit unbinds the previously-bound texture.


glBindTexture( GL_TEXTURE_2D_ARRAY, 0 );

It’s worth mentioning that a way around needing to bind textures before you can modify their parameters is to use what’s termed “direct state access” APIs. These allow you to specify the object handle directly in the API call, rather than have to bind the object to some binding point first before you reference it indirectly through that bind point.

For instance, this:


glTextureParameteri( myTextureHandle, GL_TEXTURE_MIN_FILTER, GL_LINEAR );

will do the same thing as the above, but without having to bind the texture to a texture unit/target.

This does nothing. Do you see why?

Thanks. I tried unbinding it for debugging purposes but still nothing. Quite possibly it’s the engine not allowing it somehow…

Originally Posted by SpiderPig500[i]Code :
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, _width, _height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);

[/i]

This does nothing. Do you see why?

Ah yes. Sorry. It’s a typo from copying it over to here. I have fixed the original post. Thanks for spotting that.

I’ve also seen this before;

Uniform sampler2D texture [3]

How does this vary from texture arrays? Does it allow for more textures per slot? Or does each element use a slot?

[QUOTE=SpiderPig500;1292466]
I’ve also seen this before;

Uniform sampler2D texture [3]

How does this vary from texture arrays?[/QUOTE]
The disadvantages of an array of samplers are that each texture requires a separate texture unit, and array indices must be dynamically uniform (in the vertex shader they must be constant for all vertices in a draw call, in the fragment shader they must be constant for all fragments within a primitive).

The advantages are that textures can be different sizes or formats and can have different sampling parameters (filter modes, wrap mode, etc).

Texture arrays are a single texture, so all layers have the same dimensions, format and sampling parameters. But they only use one texture unit and the layer index can be an arbitrary expression which can vary between vertices or fragments.

Thanks for the info. Texture Arrays are what I want then.