OpenGL mipmaps with texture arrays

Started by
4 comments, last by Misantes 9 years, 4 months ago

Hey all,

I've been trying to implement mipmapping with the images in my texture array, but I think I may be going about this wrong and I'm having difficulty tracking down an answer. I'm not receiving an error, but everything in game still looks very pixelated and jagged in the distance.

my image loading looks thusly:


void LoadAssets()
{
    //create texture array////
    glGenTextures(1, &TextureArray);
    glBindTexture(GL_TEXTURE_2D_ARRAY, TextureArray);
    glTexStorage3D(GL_TEXTURE_2D_ARRAY,1, GL_RGBA8, 1024, 1024, 9);

    //bind vertex array. Once.////
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    //load images////
    //don't change the number on the end, used for texture array placement. don't rearrange. add to end of list.
    //stone image////
    LoadImage("GAMEASSETS/StoneDiffuse.png", 0);
    LoadImage("GAMEASSETS/StoneNormal.png", 1);
    LoadImage("GAMEASSETS/StoneSpecular.png", 2);
    imageIndices.emplace_back(glm::vec3(0,1,2));

    //mountain image////
    LoadImage("GAMEASSETS/mountainDiffuse.png", 3);
    LoadImage("GAMEASSETS/mountainNormal.png", 4);
    LoadImage("GAMEASSETS/mountainSpecular.png", 5);
    imageIndices.emplace_back(glm::vec3(3,4,5));
    
    //tree image////
    LoadImage("GAMEASSETS/TreeDiffuse.png", 6);
    LoadImage("GAMEASSETS/TreeNormal.png", 7);
    LoadImage("GAMEASSETS/TreeSpecular.png", 8);
    imageIndices.emplace_back(glm::vec3(6,7,8));

    //set texture parameters////
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    
    glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
}

void LoadImage(const char* imageName, int layerNumber)
{
    if(!image.loadFromFile(imageName))
    {
        std::cout<<imageName<<" failed to load..."<<std::endl;
    }
    
    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layerNumber, image.getSize().x, image.getSize().y,1, GL_RGBA, GL_UNSIGNED_BYTE, image.getPixelsPtr());
}

So, if I'm doing things incorrectly, what is the proper way in OpenGL 3.3+ to mipmap the images in a texture array? Should I be setting the glTexParameters for every image rather than once at the end? Do I need to be changing the second parameter of glTexSubImage3D? Is the jaggedness in the textures at a distance not a mipmap problem? I do find cranking up the antialiasing helps, but it's not really feasible to keep that at 32 samples :P

To clarify though, I'm not receiving any error, but the images definitely don't look mipmapped, and become pixelated in the distance. Hopefully I'm just doing something silly here.

Anyhow, I appreciate any input, and cheers! smile.png

Beginner here <- please take any opinions with grain of salt

Advertisement

You are allocating just one mipmap level with the call to glTexStorage3D. Then you fill the base level with the loaded image, and then you ask to generate mipmaps. Because there is no level allocated above the base level (only those will be generated by glGenerateMipmap), nothing happens in the end. So try to increase the level parameter of glTexStorage3D.

I thought that may be the case. That's the second parameter, correct? When I try to increase it, everything turns solid black/white or just really....weird (kind of like an old crt monitor). Does it need to be a specific number (such as divisible by 4 or anything)? I've tried various values but all have the same effect.

Beginner here <- please take any opinions with grain of salt

I thought that may be the case. That's the second parameter, correct? When I try to increase it, everything turns solid black/white or just really....weird (kind of like an old crt monitor). Does it need to be a specific number (such as divisible by 4 or anything)? I've tried various values but all have the same effect.

It is the 2nd parameter, yes. Its value must not exceed the hardware limit as can be requested by using GL_TEXTURE_MAX_LEVEL with glGetTexParameteriv, but I doubt that you actually exceed it. It must further be so that the mipmap level with size 1 by 1 is not generated more often than once (the reference says that it must not be greater than log2(max(width,height))+1 which, in your case, computes to 11). Besides that, it may be any positive integer number.

EDIT: Oops: glGetTexParameter naturally gives you a set-up parameter, not a hardware limit.

You're calling glGenerateMipMap on an empty texture. At the point you're calling, your texture contains no data - only the memory for the texture has been allocated. If you want mipmaps to be generated for each layer you update, you need to call glGenerateMipMap every time you update the layer. Note this could potentially do unnecessary extra work and regenerate the mipmaps for the other layers as well. Alternatively, you could pre-calculate the mipmaps for the textures you're using and upload them into each mip level manually.

EDIT: Didn't notice the LoadImage calls :p What haegarr is correct - you need to allocate storage for all the mip levels.

Bleh, in my sleepy state (when I said I "thought that was the case") I was referring to and changing the value in glTexSubImage3D instead of glTexStorage3D >.<. Your advice works perfectly. Thanks again as always Haegar, You're always tremendously heflpful. I think I've learned more useful information from you than countless tutorials and books tongue.png

Beginner here <- please take any opinions with grain of salt

This topic is closed to new replies.

Advertisement