OpenGL texture upload: UNSIGNED_BYTE vs UNSIGNED_INT_8_8_8_8
Asked Answered
S

2

15

I'm calling glTexSubImage2D. If my pixel format is GL_RGBA, then are the pixel types GL_UNSIGNED_BYTE and GL_UNSIGNED_INT_8_8_8_8 fully equivalent?

Also, are these two pairs equivalent?

  • Format = GL_RGBA, Type = GL_UNSIGNED_INT_8_8_8_8
  • Format = GL_BGRA, Type = GL_UNSIGNED_INT_8_8_8_8_REV

I've tried reading the OpenGL spec and the GL_EXT_packed_pixels spec, but honestly I can't make head or tail of them.

Serranid answered 16/10, 2011 at 17:58 Comment(0)
M
28

The answers are No and No. You have to think about the byte order in your computer. If you have GL_RGBA and GL_UNSIGNED_INT_8_8_8_8, that means that pixels are stored in 32-bit integers, and the colors are in the logical order RGBA in such an integer, e.g. the red is in the high-order byte and the alpha is in the low-order byte. But if the machine is little-endian (as with Intel CPUs), it follows that the actual order in memory is ABGR. Whereas, GL_RGBA with GL_UNSIGNED_BYTE will store the bytes in RGBA order regardless whether the computer is little-endian or big-endian.

GL_BGRA with GL_UNSIGNED_INT_8_8_8_8_REV would store colors in an integer in the logical order ARGB, but then on a little-endian machine, you get BGRA order in memory.

Mcglynn answered 16/10, 2011 at 18:33 Comment(1)
It is worth pointing out that GL_UNSIGNED_BYTE and GL_UNSIGNED_INT_... in this example are the pixel transfer types. They do not say anything about how GL stores the color, only how the "packed" colors are interpreted by GL when the color data are sent to it. Sort of an important distinction because usually the goal with these more exotic formats is to match the client (CPU) and server (GPU) formats so that GL does not need to perform data conversion and can do a simple block transfer.Kingston
B
0

See JWWalker's answer first. This answer is a supplement to it. A quick illustration.

GL_RGBA stored in GL_UNSIGNED_INT_8_8_8_8:

0xrrggbbaa

GL_RGBA' stored in GL_UNSIGNED_BYTE`:

[0xrr, 0xgg, 0xbb, 0xaa]

In both cases, RGBA is in the logical order r, g, b, a, but on a little endian machine (this is the normal architecture), 0xrrggbbaa has the little byte (least-significant) stored first. If you read the uint32_t one byte at a time, you'll get 0xaa first! A C++ example:

uint32_t color{0x11223344};
uint8_t first_byte{reinterpret_cast<uint8_t*>(color)[0]};

first_byte will equal 0x44.

One thing that's confusing is the word "first". It can mean "appearing first when written" as in "The red byte is first in 0xrrggbbaa". This is different from "having the lowest memory/pointer address" as in "The alpha byte is first in 0xrrggbbaa when encoded using little-endian"! When you use GL_RGBA, it sure looks like red will be first, but when encoded in a 4-byte integer little endian, it is only that way in the hex representation.

Bouse answered 7/12, 2021 at 13:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.