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\$ – david van brink Aug 11 '15 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\$ – Ivan Kuckir Aug 12 '15 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\$ – david van brink Aug 12 '15 at 19:10

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\$ – Ivan Kuckir Aug 11 '15 at 21:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.