documentation表示这会为纹理及其级别“分配”存储空间。提供的伪代码似乎表明这是针对mipmap级别的。
glTexStorage
的使用与glGenerateMipmap
的关系如何? glTexStorage
似乎“锁定”纹理的存储大小。在我看来,这只会使事情变得不那么灵活。是否意味着要在这里获得性能提升?
这是非常新的,只能在4.2中使用,所以我会尽量避免使用它,但我很困惑,因为它的描述使它听起来很重要。
如何在早期GL版本中管理纹理存储?当我调用glTexImage2D
时,我有效地擦除并释放先前与纹理句柄关联的存储空,是吗?并且生成mipmap也会自动为我处理存储空间。
我记得使用旧式glTexSubImage2D
方法实现OpenGL 2样式渲染到纹理,以便在我之前的引擎实验中执行一些后期处理效果。因为我们有更好的方法来进行RTT,glTexStorage
将带来一种更合理的方式来管理与纹理相关的资源,这是有道理的。
答案 0 :(得分:28)
要了解glTexStorage
的作用,您需要了解glTexImage*
函数的作用。
glTexImage2D
做了三件事:
GL_PIXEL_UNPACK_BUFFER
),则不会发生像素传输。手动创建mipmap纹理需要一系列glTexImage
次调用,每个mipmap级别一次。 mipmap级别的每个大小都必须是基于先前级别大小的适当大小。
现在,如果你看一下GL 4.2规范的第3.9.14节,你会看到两页规则,纹理对象必须遵循这些规则才能“完成”。无法访问不完整的纹理对象。
在这些规则中,“mipmap必须具有适当的大小”。以上面给出的示例为例:一个64x64 2D图像,它是mipmap level 2.它将完全有效的OpenGL代码来分配使用256x256纹理的mipmap level 1。或16x16。或10x345。就源代码而言,所有这些都将是完美的功能。显然,它们会产生无意义的纹理,因为纹理不完整。
再次考虑64x64 mipmap 2.我将其创建为我的第一张图片。现在,我可以创建一个128x128 mipmap 1.但是我可以 创建一个128x12 9 mipmap 1.这两个都是完全与64x64 mipmap级别2一致的(mipmap大小始终向下舍入)。虽然它们都是一致的,但它们也都是不同的尺寸。如果驱动程序必须立即分配完整的mipmap链(这是完全可能的),它分配的大小是多少?它不知道。直到您明确分配其余部分才能知道。
这是另一个问题。假设我有一个带有完整mipmap链的纹理。根据规则,它完全是纹理完整的。然后我再次打电话给glTexImage2D
。怎么办?我可能会意外更改内部格式。每个mipmap级别都有一个单独的内部格式;如果他们不同意,那么纹理是不完整的。我可能会意外地改变纹理的大小,再次使纹理不完整。
glTexStorage
可以防止所有这些可能的错误。考虑到基本级别的大小,它会创建您想要的所有mipmap。它使用相同的图像格式分配所有这些mipmap,因此你无法搞砸它。它使纹理不可变,所以你不能出现并尝试通过错误的glTexImage2D
调用来破坏纹理。并且它可以防止我甚至懒得解决的其他错误。
问题不在于“glTexStorage做什么?”问题是“为什么我们这么长时间没有它。”
glTexStorage
与glGenerateMipmap
无关;它们是正交功能。 glTexStorage
完全按照它所说的做法:它分配纹理存储空间。它没有用任何东西填充那个空间。因此,它会创建一个给定大小的纹理,并填充未初始化的数据。就像glRenderbufferStorage
分配一个填充了未初始化数据的给定大小的渲染缓冲区一样。如果您使用glTexStorage
,则需要使用glTexSubImage
上传数据(因为glTexImage
在不可变纹理上是禁止的。)
glTexStorage
为mipmap创建空间。 glGenerateMipmap
自己创建mipmap数据(基础层的较小版本)。如果该空间尚不存在,它还可以为mipmap创建空间。它们用于两种不同的事情。
答案 1 :(得分:2)
在调用glGenerateMipmap
之前,必须建立基本mipmap级别。 (使用可变或不可变的存储).so ...,您只能使用glTexImage2D+glGenerateMipmap
,更简单!