如何获取 Webgl 纹理的副本

How do I Get Copy of Webgl Texture

我有一个 webgl 纹理,我将这个纹理存储在一个 javascript 变量中

var texture1 = CreateTexture()

function CreateTexture(){
  var texture = gl.createTexture()
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false)
  gl.bindTexture(gl.TEXTURE_2D, texture)
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,canvas)
  gl.generateMipmap(gl.TEXTURE_2D)
  gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
  gl.texParameterf(gl.TEXTURE_2D, this.extAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT, 2)
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true)
  return texture
}

我想在另一个变量而不是实例中保留此纹理 (texture1) 的副本。 例如对于 javascript 数组,多亏了 slice 函数,我们可以在变量中保留数组的副本。

var arr1 = [1,2,3,4,5]
var arr2 = arr1.slice()

如何为 webgl 纹理执行此操作?

没有简单的方法,也不能保证您可以复制纹理。

要复制纹理,您需要 render to a texture。所以你设置了一个着色器和属性和制服来绘制源纹理,将目标纹理附加到帧缓冲区,绑定帧缓冲区,绘制。

你也可以使用copyTexImage2D。如果没有绑定帧缓冲区,它会从当前帧缓冲区或 canvas 复制,因此在这种情况下,您获取源纹理,将其附加到帧缓冲区,绑定帧缓冲区,绑定目标纹理,调用 copyTexImage2D.

两种方法的限制是

  1. 并非每种格式的纹理都可以用作帧缓冲区的附件。例如,在 WebGL1 中,只有 format/type RGBA/UNSIGNED_BYTE 的纹理可以保证能够附加到帧缓冲区

  2. 您无法在 WebGL1 中查询纹理的大小,因此您需要自己将其保存在某个地方

  3. 您无法查询内部格式,也无法查询纹理的格式或类型,因此您必须保存它。请注意,在 WebGL2 中,每个 mip 具有与任何其他 mip 无关的大小以及不同的内部格式都是合法的,只要设置纹理的基本和最大 LOD,以便使用的 mip 范围有效。这意味着对于通用副本,您需要保存每个 mip 级别的尺寸和内部格式。

  4. 您无法查询有多少个 mip,因此如果您需要,则需要保存该信息

  5. 即使知道有多少 mip,也无法轻易复制它们

    对于 1,您不能将级别 0 以外的 mip 绑定到帧缓冲区。这意味着第一种方法不适用于复制 mip,因为您无法将 mip 指定为复制的目标。对于第二种方法,您不能将 mip 指定为副本的源,因此您需要编写一个着色器,将该 mip 渲染到 canvas 或另一个纹理,然后调用 copyTexImage2D 将其放入mip.

    如果您不关心 mip 的内容,您可以只复制级别 0 并调用 generateMipmap

  6. 不能复制未处于可渲染状态的纹理。

    例如 WebGL1 中的 a 具有非 2 的幂纹理和过滤 设置为使用 mips 或重复。或者如果 mip 的大小不正确或 不同的格式。

对于像TEXTURE_MIN_FILTERTEXTURE_WRAP_S这样的参数,你可以调用gl.getTextureParameter从一个纹理中查询它们并将它们应用到另一个纹理,或者你可以像问题2一样自己保存它们,和以上 3