I have a matrix of pixels in RAM memory, e.g. 1000x1000 pixels. I send it to GPU using

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1000,1000, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

Which works great. But then I change some pixels, located in rectangle x=50, y=50, width =100, height=100. Sending the whole 1000x1000px picture again takes too much time, I would like to send only changed sub-area to the GPU.

I have tired

gl.texSubImage2D(gl.TEXTURE_2D, 0, 50,50, 100,100, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

but it seems, that parameter "pixels" should be the sub-area of 100x100 pixels. Copying out a sub-area from a large picture also takes too much time. Can I somehow specify a sub-rectangle for source pixels in RAM? Maybe somehow using gl.pixelStorei() ?

UPDATE: I discovered that it is possible in WebGL 2.0 (= OpenGL ES 3.0) using gl.pixelStorei() by changing PACK_ROW_LENGTH, PACK_SKIP_ROWS, PACK_SKIP_PIXELS parameters. Too bad WebGL 2.0 is not supported in most of devices now :(

  • \$\begingroup\$ How many times per frame do you need to do this? (And is your texture actually 1000x1000 or was that just to explain?) \$\endgroup\$ Aug 11, 2015 at 21:53
  • 1
    \$\begingroup\$ I am creating WebGL acceleration for photopea.com photo editor. User would draw using Brush into layer. Each layer must be on the GPU for fast blending. Project may have a layer of 4000x3000 px (4 channels => 48 MB), which may be changed in every frame (as mouse moves). To get 60fps, I need to send 2.9 GB per second. \$\endgroup\$ Aug 12, 2015 at 18:44
  • \$\begingroup\$ @Adam's solution is good, just sending whole rows as the mouse moves, since true subrects aren available. You could also have a maximum per frame, and if more than that change, throttle it out over several frames. \$\endgroup\$ Aug 12, 2015 at 19:10

1 Answer 1


I don't think it's possible to specify a source pitch for the buffer in CPU memory like you could with a lower level API.

However, you can specify an offset into your pixels using a DataView, so you could upload a 1000x100 portion of the texture that way.

  • \$\begingroup\$ That is a nice solution! But in my case, sub-areas are not too wide, so copying out 100x100 sub-area into separate array would be faster, than uploading a 1000x100 wide stripe. \$\endgroup\$ Aug 11, 2015 at 21:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .