关于opengl:如何调整帧缓冲区中现有纹理附件的大小?

How can I resize existing texture attachments at my framebuffer?

调整窗口大小时,需要调整附加到帧缓冲区的纹理的大小。 我尝试使用不同的大小参数再次调用glTexStorage2D。 但是,这不起作用。

如何调整附加到帧缓冲区的纹理的大小? (包括深度附件)

编辑

我试过的代码:

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

其中m_name,m_target和m_format是从原始纹理保存的,而m_width和m_height是新尺寸。

编辑2

请告诉我为什么这个问题被否决了,所以我可以解决这个问题。

编辑3

在这里,其他人也有同样的问题。

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.

但是,他使用着色器修复了此问题。 那不是我想要的方式。 必须有另一种解决方案,对不对?


如果使用glTexImage2D (...)为纹理分配存储空间,则可以随时为纹理中的任何图像重新分配存储空间,而无需先删除纹理。

但是,您没有使用glTexImage2D (...),而是正在使用glTexStorage2D (...)。这将创建一个不变的纹理对象,其存储需求只设置一次,就无法再更改。最初在分配存储空间之后,对glTexImage2D (...)glTexStorage2D (...)的任何调用都将生成GL_INVALID_OPERATION,并且不执行其他任何操作。

如果要创建可以随时更改大小的纹理,请不要使用glTexStorage2D (...)。而是将一些虚拟(但兼容)的数据类型和格式值传递给glTexImage2D (...)

例如,如果您要分配一个具有m_width x m_height的1 LOD的纹理:

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

如果m_widthm_height稍后更改,则可以使用以下方式重新分配存储:

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

这与使用glTexStorage2D (...)的情况大不相同。这将阻止您重新分配存储,并且只会创建一个GL_INVALID_OPERATION错误。

您应该查看手册页中的glTexStorage2D (...),其中指出以下内容:

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.

当target为GL_TEXTURE_2D, GL_PROXY_TEXTURE_2DGL_TEXTURE_RECTANGLEGL_PROXY_TEXTURE_RECTANGLEGL_PROXY_TEXTURE_CUBE_MAP时,假设没有生成错误,调用glTexStorage2D等效于执行以下伪代码:

1
2
3
4
5
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));
}

当目标为GL_TEXTURE_CUBE_MAP时,glTexStorage2D等效于:

1
2
3
4
5
6
7
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));
}

当目标为GL_TEXTURE_1DGL_TEXTURE_1D_ARRAY时,glTexStorage2D等效于:

1
2
3
4
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.