如何在我的帧缓冲区调整现有纹理附件的大小?

时间:2014-04-29 10:49:09

标签: opengl fbo

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

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

修改

我试过的代码:

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是新维度。

EDIT2

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

EDIT3

Here,其他人也有同样的问题。

  

我发现纹理正确地呈现给FBO,但它显示的大小错误。就好像第一次将纹理发送到默认帧缓冲区时,纹理大小是永久设置的,然后当发送一个调整大小的纹理时,它被视为原始大小。例如,如果第一个纹理为100x100,第二个纹理为50x50,则整个纹理将显示在屏幕的左下角。相反,如果原始纹理为50x50,新纹理为100x100,则结果将是整个屏幕上显示的纹理的左下角四分之一。

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

1 个答案:

答案 0 :(得分:20)

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

但是,您使用glTexImage2D (...) ,您正在使用glTexStorage2D (...)。这会创建一个 不可变的 纹理对象,其存储要求设置一次,永远不会再次更改。在您最初分配存储空间后,对glTexImage2D (...)glTexStorage2D (...)的任何来电都会生成GL_INVALID_OPERATION,而不会执行任何操作。

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


例如,如果要分配一个纹理,其中1个LOD为m_width x m_height

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

如果稍后更改m_widthm_height,您可以采用相同的方式重新分配存储空间:

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

这种情况与使用glTexStorage2D (...)的情况完全不同。这将阻止您重新分配存储空间,并且只会创建GL_INVALID_OPERATION错误。


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

  

<强>描述

     
    

glTexStorage2D同时指定二维纹理或一维纹理阵列的所有级别的存储要求。 使用此命令指定纹理后,除非是代理纹理,否则所有级别的格式和尺寸都将变为不可变。 图像的内容可能仍会被修改,< strong> 但是,其存储要求可能不会更改 。这种纹理称为 不可变格式纹理

         

glTexStorage2D 的行为取决于目标参数。

  

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

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 相当于:

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 相当于:

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

由于实际上没有提供纹理数据,因此formattype的伪代码中使用的值无关紧要,可以认为是 任何合法的值所选internalformat枚举的 。 [...]成功后,GL_TEXTURE_IMMUTABLE_FORMAT的值变为GL_TRUE。可以通过调用 glGetTexParameter 并将GL_TEXTURE_IMMUTABLE_FORMAT设置为pname来发现GL_TEXTURE_IMMUTABLE_FORMAT的值。不能进一步改变纹理对象的尺寸或格式。使用可能改变纹理对象的尺寸或格式的任何命令(例如 glTexImage2D 或对 glTexStorage2D 的另一次调用)将导致生成GL_INVALID_OPERATION错误,即使它实际上不会改变对象的尺寸或格式。