我正在尝试在 webgl2 中使用 3D 纹理,并且我开始了解
gl.texImage3D();
Run Code Online (Sandbox Code Playgroud)
我有 2D 纹理的经验,我发现它非常方便,但人们在互联网上使用另一种方法。
gl.texStorage3D()
Run Code Online (Sandbox Code Playgroud)
进而,
gl.texSubImage3D() // with all offset of x,y and z as 0.
Run Code Online (Sandbox Code Playgroud)
我只是想知道这两种方法有什么区别。我开始知道,第二个选项的等效项也可用于 2D 纹理,但我不使用它来向目标提供数据。我知道子图像是为片段着色器创建纹理的子图像,但我不明白两种方法之间有什么区别。
简短的答案是texStorage2D预先texStorage3D分配所有纹理内存。其中 astexImage2D和texImage3D一次分配一个 mip 级别。
texSubImage2D并且texSubImage3D不分配任何东西。它们只是将数据复制到之前使用上述函数之一分配的纹理 mip 级别中。
至于为什么其中之一。texStorage2D并且texStorage3D可以立即在GPU上分配内存。texImage2D并且texImage3D不能,因为他们不知道完整的纹理(所有 mip),直到您实际尝试使用纹理绘制某些内容。换句话说, as更灵活,效率texStorage2D/3D 可能更高。texImage2D/3D
为了使纹理真正可渲染,您要使用的所有 mip 级别都需要具有相同的内部格式和正确的大小。
当您调用时,texStorage2D/3D您会告知 mip 级别 0(最大级别)的大小以及总共要分配多少个 mip 级别。假设您告诉它内部格式为gl.RGBA88 和 4 个 mip 级别的宽度和高度。
gl.texStorage2D(gl.TEXTURE_2D,
4, // 4 levels
gl.RGBA8, // internal format
8, // width
8); // height
Run Code Online (Sandbox Code Playgroud)
它将分配 8x8x4、4x4x4、2x2x4、1x1x4 mip 级别,所有 4 个 mip 级别。它知道它们都是 RGBA8。它知道它们的尺寸都是正确的。分配的纹理的texStorage2D大小或内部格式不能更改。如果您尝试调用texImage2D用您创建的纹理,texStorage2D您将收到错误。
如果你首先使用texImage2Dwell,你可能会指定第一个mip
gl.texImage2D(gl.TEXTURE_2D,
0, // mip level
gl.RGBA8, // internal format
8, // width
8, // height
0, // border
gl.RGBA, // data format
gl.UNSIGNED_BYTE, // data type
data);
Run Code Online (Sandbox Code Playgroud)
所以现在你只有 1 个 mip 级别,级别 #0。您会添加其他 3 mips 吗?它们的尺寸正确吗?其他 3 个 mip 是否具有相同的内部格式?您会将 mip 级别 #0 更改为其他内容、不同的大小或不同的内部格式吗?WebGL 不知道您的下一个命令是什么,它必须等到您实际尝试使用纹理进行绘制后才能进行检查。您可以texStorage预先决定所有 mip 的大小和格式,因此只需检查一次。您不必texImage预先告诉它所有内容,因此如果情况发生变化,它必须在抽奖时再次检查。