The general idea is that I have an image and its n precalculated mipmaps in files in disk, what I want is to create an empty texture and manualy copy the mipmaps in this texture.
What I currently do is, at first, to create an empty texture and then create the (dummy) mipmaps:
glTexImage2D(target, 0, internalFormat, width, height, 0, format, type, NULL);
glGenerateMipmap(target);
It seems that glTexSubImage can copy data from RAM to the texture’s mipmaps directly:
int level = 1;
glTexSubImage2D(target, level, 0, 0, width / 2, height / 2, format, type, imageBufferForMipmap1); // Copy data to the second mipmap
Everything works as it should but there is a problem. When I copy something to the base mipmap (level 0) the driver discards the previous mipmaps and recalculates them. For example if I copy a green texture in level 2 mipmap and then copy a red in the base level mipmap everything turns into red.
I dont know if the glTexSubImage is the right way to copy to texture’s mipmaps but how can I copy to the base level mipmap without opengl recreating the previous mipmaps?
Thanks in advance.
PS: This will be used for texture streaming (async loading)
That sounds like a driver problem, and as if your driver is automatically renenerating sublevels if the top level is changed. Definitely shouldn’t happen.
You might be better off just dropping your usage of glGenerateMipmap and generating your sublevels manually instead.
What he’s saying is that you should be using glTexImage2D to allocate mipmaps instead of glGenerateMipmap. Just call glTexImage2D for each mipmap you have.
Yeah, this is the correct interpretation. Using a combination of glGenerateMipmap to initially specify the miplevels, then glTexSubImage2D to subsequently update individual miplevels seems to be what generates this bug, so switching to pure glTexImage2D for initial specification of all miplevels was what I had in mind.
First of all sorry for the late update, due to lack of time I’ve tested it yesterday.
I’ve tried to specify the textures for every mipmap level using glTexImage2D. I didnt create any mipmaps with glGenMipmaps() and it worked like a charm. See the simple test case for that:
int target = GL_TEXTURE_2D;
int internalFormat = GL_RGBA;
int format = GL_RGBA;
int type = GL_UNSIGNED_BYTE;
glGenTextures(1, &glId);
glActiveTexture(GL_TEXTURE0);
glBindTexture(target, glId);
setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int w = 100, h = 100;
int level = 0;
while(1)
{
uint col = rand();
Vec<uint> buff(w * h, col);
glTexImage2D(target, level, internalFormat, w, h, 0, format, type, &buff[0]);
++level;
w /= 2;
h /= 2;
if(w == 0 || h == 0)
{
break;
}
}
When using texture sizes that are not powers of two, the half-size of lower mipmaps is rounded down. So a 63x63 texture has as its next lowest mipmap level 31x31. And so on.