7

我确实使用 gltexSubImage2D() 更新到 OpenGL 4.0 中的纹理 2D。纹理具有使用自动生成的 mipmap

 glGenerateMipmap(GL_TEXTURE_2D); 

我的纹理更新失败,直到我明白我也必须在更新时重新生成 mipmaps(或删除 mipmaps 生成)。然后我阅读了这个wiki,其中在生成 mipmaps 时使用了glTexStorage2D 。我实际上从未关注过这种方法。所以我想知道每次使用 mipmap 生成纹理时是否必须使用它?

更新 :

我从方法规范中看到它

同时指定二维纹理或一维纹理数组的所有级别的存储要求

我猜使用它应该可以提高生成 mipmap 时的性能?是真的吗?

4

2 回答 2

29

这两个函数是完全正交的。

选择在glTexImage2D和之间glTexStorage2D。这两个都为纹理图像分配存储空间;他们只是以不同的方式做到这一点。

glTexImage2D是分配存储的旧方式。它创建可变存储(还有其他函数也可以创建可变存储)。如果您想要 mipmap,则必须通过单独调用函数来分配每个 mipmap 级别,手动计算 mipmap 图像的大小(请参阅下面的例外情况)。

glTexStorage2D为图像数据分配不可变的存储空间。它一次性分配所有你想要的 mipmap。

顾名思义,不可变存储无法更改。看,你可以调用glTexImage2D相同的 mipmap 级别,但大小不同。如果你这样做了,OpenGL 将破坏原来的 mipmap 层并为新层分配存储空间。您甚至可以更改格式。

不可变存储不会让您更改任何内容。您可以使用glTexSubImage2D. 但是这些功能不会改变存储;他们改变了内容。

glTexImage2D并且glTexStorage2D喜欢mallocglTexSubImage2D就像memcpy; 它仅适用于现有内存。

glGenerateMipmap是一个函数,它将获取纹理的基础层并为来自该基础层的所有 mipmap 生成数据(给定 mipmap 范围)。它会这样做一次。把它想象成一个渲染函数;它完成了它的工作,然后就完成了。

对于可变存储纹理,glGenerateMipmap还将为先前未分配的 mipmap 范围内的任何 mipmap 分配存储。这就是为什么您可以调用glTexImage2D一次,然后调用glGenerateMipmap强制它制作所有其他 mipmap,而无需手动执行。

于 2013-03-14T10:35:06.910 回答
11

在 glTexStorage 出现之前,每个 mipmap 级别都必须通过单独调用 glTexImage 来初始化。glTexImage 会触发很多复杂的内部状态变化,这些变化是相当昂贵的。每次调用 glTexImage 时,纹理对象的布局都会改变。

因此,如果可能,请尽量避免使用它。正如您所发现的,您必须先初始化所有所需的 mipmap 级别,然后才能通过 glTexSubImage 更新它们。glGenerateMipmap 将创建它们,这会引入布局更改,是的,很昂贵。

glTexStorage 将整个纹理对象初始化一次,以获得所需的不可变格式。是的,当与 glGenerateMipmap 或 glTexSubImage 的数据更新一起使用时,使用 glTexStorage 可以提高性能,但是这些改进发生在纹理对象创建的早期,而不是在其数据更改时。

于 2013-03-14T10:35:27.703 回答