Error when creating textures in WebGL with the RGB

2019-07-16 18:59发布

Trying to create a 1px x 4px texture from data with the RGBA format like so works:

const texture = gl.createTexture()
gl.activeTexture(gl.TEXTURE0)
gl.bindTexture(gl.TEXTURE_2D, texture)
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([
  255, 0, 0, 255,
  0, 255, 0, 255,
  0, 0, 255, 255,
  255, 255, 0, 255
]))
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)

However trying to do the same with the RGB format like so:

const texture = gl.createTexture()
gl.activeTexture(gl.TEXTURE0)
gl.bindTexture(gl.TEXTURE_2D, texture)
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 4, 0, gl.RGB, gl.UNSIGNED_BYTE, new Uint8Array([
  255, 0, 0,
  0, 255, 0,
  0, 0, 255,
  255, 255, 0
]))
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)

Gives this error in Firefox:

Error: WebGL warning: texImage2D: Desired upload requires more data than is available: (3 rows plus 1 pixels needed, 3 rows plus 0 pixels available)

And this error in Chrome:

WebGL: INVALID_OPERATION: texImage2D: ArrayBufferView not big enough for request

Swapping the width and height parameters of gl.texImage2D so I have a 4px x 1px texture then works with gl.RGB, but a 2px x 2px texture does not. What am I getting wrong / misunderstanding here?

1条回答
混吃等死
2楼-- · 2019-07-16 19:17

Since WebGL 1.0 is based on OpenGL ES 2.0 API i will refer to OpenGL ES 2.0 refpages glPixelStorei

GL_UNPACK_ALIGNMENT

Specifies the alignment requirements for the start of each pixel row in memory. The allowable values are 1 (byte-alignment), 2 (rows aligned to even-numbered bytes), 4 (word-alignment), and 8 (rows start on double-word boundaries).

The initial value for the UNPACK_ALIGNMENT alignment parameter is 4.

If you specify a RGB texture with a width of 4 pixels, then the size of one line in 3 * 4 = 12 bytes.
If the height of the texture is 1, then the expected size of the texture is 12 * 1 = 12.

But, if you specify a RGB texture with a with of 1 pixel, then the size of one line in 3 * 1 = 3 bytes.
If UNPACK_ALIGNMENT is 4, then this size is aligned to 4 bytes.
If the height of the texture is 4, then the expected size of the texture is 4*4 = 16 bytes.

The second case does not match the data array which you use to initialize the texture and this causes the error.

To solve the issue you have to align each line of the texture to 4 bytes:

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 4, 0, gl.RGB, gl.UNSIGNED_BYTE, new Uint8Array([
    255, 0,   0,   0, // add 1 byte for alignment to 4 bytes
    0,   255, 0,   0, // add 1 byte
    0,   0,   255, 0, // add 1 byte
    255, 255, 0,   0  // add 1 byte
]))

or to set the gl.UNPACK_ALIGNMENT paramter to 1 by gl.pixelStorei:

gl.pixelStorei( gl.UNPACK_ALIGNMENT, 1 )
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 4, 0, gl.RGB, gl.UNSIGNED_BYTE, new Uint8Array([
    255, 0,   0,
    0,   255, 0,
    0,   0,   255,
    255, 255, 0
]))
查看更多
登录 后发表回答