Skip to content
Advertisement

How do I Get Copy of Webgl Texture

I have a webgl texture and I store this texture in a javascript variable

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
}

I want to keep a copy of this texture (texture1) in another variable, not instance. For example for javascript arrays, thanks to the slice function, we can keep a copy of arrays in a variable.

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

How do I do this for webgl textures?

Advertisement

Answer

There is no easy way, nor is it guaranteed you can copy a texture.

To copy texture you need to render to a texture. So you setup a shader and attributes and uniforms to draw the source texture, attach the destination texture to a framebuffer, bind the framebuffer, draw.

You can also use copyTexImage2D. It copies from the current framebuffer or canvas if no framebuffer is bound so in that case you take your source texture, attach it to a framebuffer, bind the framebuffer, bind your destination texture, call copyTexImage2D.

Limitation for both methods are

  1. not every format of texture can be used as an attachment to a framebuffer. For example in WebGL1 only a texture of format/type RGBA/UNSIGNED_BYTE is guaranteed to be able to be attached to a framebuffer

  2. You can not query the size of a texture in WebGL1 so you’ll need to have saved that somewhere on your own

  3. You can not query the internal format nor format or type of a texture so you’d have to save that. Note that in WebGL2 it’s legal for every mip to have a size unrelated to any other mip as well as different internal formats as long as the base and max LODs for the texture are set such that the range of mips used is valid. That means for a generic copy you’d need to save the dimensions of and internal format of every mip level.

  4. You can not query how many mips there are so you’ll need to save that info if you care

  5. You can not easily copy the mips even if you knew how many there are

    For 1 you can not bind a mip except level 0 to a framebuffer. This means the first method won’t work for copying mips since you can’t specify a mip as the destination for the copy. For the second method you can’t specify a mip as the source for the copy so you’d need to write a shader that renders that mip either to the canvas or a another texture and then calls copyTexImage2D to get it into the mip.

    If you don’t care about the contents of the mips you can just copy the level 0 and call generateMipmap

  6. You can not copy a texture if it’s not in a renderable state.

    For example a in WebGL1 with a non-power of 2 texture and filtering set to use mips or repeat. Or if the mips are the incorrect sizes or different formats.

For the parameters like TEXTURE_MIN_FILTER and TEXTURE_WRAP_S you can call gl.getTextureParameter to query them from one texture and apply them to another, or you can save them yourself like issues 2, and 3 above

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement