TexturesGL 1.0

glPixelStorei

Tells OpenGL how pixel rows are laid out in your memory, for uploads (unpack) and readbacks (pack).

Signature

void glPixelStorei(GLenum pname, GLint param);

How it works

By default OpenGL assumes every row of your image starts on a 4-byte boundary (GL_UNPACK_ALIGNMENT = 4). An RGBA image always satisfies that. An RGB image 3 bytes per pixel, or a one-channel glyph, usually does not: a row of 101 RGB pixels is 303 bytes, OpenGL skips one byte to reach 304, and each row starts one byte later than the last. The texture comes out slanted diagonally, with colours shifting.

Setting GL_UNPACK_ALIGNMENT to 1 says "rows are packed tightly", which is how stb_image and FreeType give you their data.

Parameters

pnameGLenum

Which setting.

Common values

GL_UNPACK_ALIGNMENT
Row alignment of data you upload (glTexImage2D, glTexSubImage2D): 1, 2, 4 or 8.
GL_PACK_ALIGNMENT
Row alignment of data you read back (glReadPixels).
GL_UNPACK_ROW_LENGTH
Pixels per row of the whole source image, to upload a sub-rectangle of it.
paramGLint

The value: 1 is always safe for alignment.

Tips & pitfalls

  • It is global state that stays set; setting it to 1 once at start-up is harmless.

Errors

When the call is invalid it does nothing and sets an error, which glGetError returns:

GL_INVALID_VALUE
An alignment other than 1, 2, 4 or 8.

Example

example.cpp
1glPixelStorei(GL_UNPACK_ALIGNMENT, 1);   // tightly packed RGB / single-channel data
2glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
Official Khronos documentation