简体   繁体   中英

How to handle 3d texture on webgl2

I am trying to work with 3D texture in webgl2 and I came to know about the

gl.texImage3D();

I have experience with 2d texture and I found it very convenient but there is another approach that people are using on the internet.


gl.texStorage3D()

and then,

gl.texSubImage3D() // with all offset of x,y and z as 0.

I just want to know what is the difference between the two approaches. I came to know that equivalent of the second option is available for the 2D texture as well but I don't use it to provide data to the target. I know that subimage is to create texture's subimage to the fragment shader but I don't understand what is the difference between two approaches.

The short answer is texStorage2D and texStorage3D allocate all of the texture memory up front. Where as texImage2D and texImage3D allocate one mip level at a time.

texSubImage2D and texSubImage3D do not allocate anything. They just copy data into a texture mip level that was previously allocated with one of the functions above.

As for why one or the other. texStorage2D and texStorage3D can immediately allocate memory on the GPU. texImage2D and texImage3D can not since they don't know the complete texture (all the mips) until you actually try to draw something with the texture. To put it another way, texStorage2D/3D might be more efficient where as texImage2D/3D is more flexible.


In order for a texture to actually be renderable, all the mip levels you are going to use need to be the same internal format and the correct sizes.

When you call texStorage2D/3D you tell the size of mip level 0 (the largest level) and how many mip levels in total to allocate. So let's say you tell it an internal format of gl.RGBA8 , width and height of 8 and 4 mip levels.

gl.texStorage2D(gl.TEXTURE_2D,
                4,         // 4 levels
                gl.RGBA8,  // internal format
                8,         // width
                8);        // height
                

It will allocate 8x8x4, 4x4x4, 2x2x4, 1x1x4 mip levels, all 4 mip levels. It knows they are all RGBA8. It knows they are all the correct size. Textures allocated with texStorage2D can't be changed in size or internal format. If you try to call texImage2D on a texture created with texStorage2D you'll get an error.

If you instead used texImage2D well first you probably specify the first 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);

so now you have just 1 mip level, level #0. Will you add the other 3 mips? Will they be the correct size? Will those other 3 mips have the same internal format? Will you change mip level #0 to something else, a different size, or different internal format? WebGL doesn't have any idea what your next command will be, it has to wait until you actually try to draw with the texture before it can check. With texStorage you decide the sizes and formats of all the mips up front so it only has to check one time. With texImage you don't tell it everything up front so it has to check at draw time again if things change.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM