How can I resize existing texture attachments at my framebuffer?
Asked Answered
F

1

24

When I resize my window, I need to resize my textures that are attached to my framebuffer. I tried calling glTexStorage2D again, with different size parameters. However that does not work.

How can I resize the textures attached to my framebuffer? (Including the depth attachment)

EDIT

Code I tried:

glBindTexture(m_target, m_name);
glTexStorage2D(m_target, 1, m_format, m_width, m_height);
glBindTexture(m_target, 0);

where m_name, m_target and m_format are saved from the original texture and m_width and m_height are the new dimensions.

EDIT2

Please tell me why this has been downvoted so I can fix the question.

EDIT3

Here, someone else had the same problem.

I found that the texture was being rendered correctly to the FBO, but that it was being displayed at the wrong size. It was as if the first time the texture was sent to the default framebuffer the texture size was set permanently, and then when a resized texture was sent it was being treated as if it was the original size. For example, if the first texture was 100x100 and the second texture was 50x50 then the entire texture would be displayed in the bottom left quarter of the screen. Conversely, if the original texture was 50x50 and the new texture 100x100 then the result would be the bottom left quarter of the texture being displayed over the whole screen.

However, he uses a shader to fix this. That's not how I want to do this. There has to be another solution, right?

Fabre answered 29/4, 2014 at 10:49 Comment(1)
You will have to re-create the texture handle.Cartierbresson
B
31

If you were using glTexImage2D (...) to allocate storage for your texture, it would be possible to re-allocate the storage for any image in the texture at any time without first deleting the texture.

However, you are not using glTexImage2D (...), you are using glTexStorage2D (...). This creates an immutable texture object, whose storage requirements are set once and can never be changed again. Any calls to glTexImage2D (...) or glTexStorage2D (...) after you allocate storage initially will generate GL_INVALID_OPERATION and do nothing else.

If you want to create a texture whose size can be changed at any time, do not use glTexStorage2D (...). Instead, pass some dummy (but compatible) values for the data type and format to glTexImage2D (...).


For instance, if you want to allocate a texture with 1 LOD that is m_widthxm_height:

glTexImage2D (m_target, 0, m_format, m_width, m_height, 0, GL_RED, GL_FLOAT, NULL);

If m_width or m_height change later on, you can re-allocate storage the same way:

glTexImage2D (m_target, 0, m_format, m_width, m_height, 0, GL_RED, GL_FLOAT, NULL);

This is a very different situation than if you use glTexStorage2D (...). That will prevent you from re-allocating storage, and will simply create a GL_INVALID_OPERATION error.


You should review the manual page for glTexStorage2D (...), it states the following:

Description

glTexStorage2D specifies the storage requirements for all levels of a two-dimensional texture or one-dimensional texture array simultaneously. Once a texture is specified with this command, the format and dimensions of all levels become immutable unless it is a proxy texture. The contents of the image may still be modified, however, its storage requirements may not change. Such a texture is referred to as an immutable-format texture.

The behavior of glTexStorage2D depends on the target parameter.

When target is GL_TEXTURE_2D, GL_PROXY_TEXTURE_2D, GL_TEXTURE_RECTANGLE, GL_PROXY_TEXTURE_RECTANGLE or GL_PROXY_TEXTURE_CUBE_MAP, calling glTexStorage2D is equivalent, assuming no errors are generated, to executing the following pseudo-code:

for (i = 0; i < levels; i++) {
    glTexImage2D(target, i, internalformat, width, height, 0, format, type, NULL);
    width = max(1, (width / 2));
    height = max(1, (height / 2));
}

When target is GL_TEXTURE_CUBE_MAP, glTexStorage2D is equivalent to:

for (i = 0; i < levels; i++) {
    for (face in (+X, -X, +Y, -Y, +Z, -Z)) {
        glTexImage2D(face, i, internalformat, width, height, 0, format, type, NULL);
    }
    width = max(1, (width / 2));
    height = max(1, (height / 2));
}

When target is GL_TEXTURE_1D or GL_TEXTURE_1D_ARRAY, glTexStorage2D is equivalent to:

for (i = 0; i < levels; i++) {
    glTexImage2D(target, i, internalformat, width, height, 0, format, type, NULL);
    width = max(1, (width / 2));
}

Since no texture data is actually provided, the values used in the pseudo-code for format and type are irrelevant and may be considered to be any values that are legal for the chosen internalformat enumerant. [...] Upon success, the value of GL_TEXTURE_IMMUTABLE_FORMAT becomes GL_TRUE. The value of GL_TEXTURE_IMMUTABLE_FORMAT may be discovered by calling glGetTexParameter with pname set to GL_TEXTURE_IMMUTABLE_FORMAT. No further changes to the dimensions or format of the texture object may be made. Using any command that might alter the dimensions or format of the texture object (such as glTexImage2D or another call to glTexStorage2D) will result in the generation of a GL_INVALID_OPERATION error, even if it would not, in fact, alter the dimensions or format of the object.

Baudekin answered 29/4, 2014 at 18:59 Comment(2)
So I shouldn't use glTexStorage if I want to resize my window?Fabre
Not if you want the texture to scale 1:1 with the window. You can always over-size your texture ahead of time, or upscale. But glTexStorage (...) prevents you from re-sizing a texture after it has been created. glTexImage2D (...), on the other hand, will allow you to change it at any time.Baudekin

© 2022 - 2024 — McMap. All rights reserved.