Skip to content

Image Format

Color attachments such as colortex and shadowcolor buffers, as well as custom images and textures, store values in different formats with varying bit depth and layout.

The default format for color attachments is RGBA (which equates to RGBA8 on most systems). However, a shader pack can specify the format using the <bufferName>Format directive.

The available image formats and their meanings are described below.

Normalized buffers store “floating point” values in a fixed range. The values are stored as integers internally, which are converted to/from floating point numbers during read/write. Any values outside the range are clamped to fit in the range.

A detailed explanation can be found on the OpenGL wiki.

Unsigned normalized buffers support values from 0.0 to 1.0 (inclusive).

Image FormatBit DepthPixel FormatPixel TypeImageRequirements
RGBA164×16RGBAUNSIGNED_SHORT✔️
RGBA84×8RGBAUNSIGNED_BYTE✔️
RGB10_A210/10/10/2RGBAUNSIGNED_INT_2_10_10_10_REV✔️
RGBA4*4×4RGBAUNSIGNED_SHORT_4_4_4_4_REV❌OpenGL 4.2+
RGB5_A15/5/5/1RGBAUNSIGNED_SHORT_1_5_5_5_REV❌OpenGL 4.2+
RGB163×16RGBUNSIGNED_SHORT❌
RGB83×8RGBUNSIGNED_BYTE❌
RGB565*5/6/5RGBUNSIGNED_SHORT_5_6_5_REV❌OpenGL 4.1+ or ARB_ES2_compatibility
RG162×16RGUNSIGNED_SHORT✔️
RG82×8RGUNSIGNED_BYTE✔️
R161×16REDUNSIGNED_SHORT✔️
R81×8REDUNSIGNED_BYTE✔️
RGBA2*4×2RGBA❌
R3_G3_B23/3/2RGBUNSIGNED_BYTE_2_3_3_REV❌
*Requires Iris 1.8+

Signed normalized buffers support values from -1.0 to 1.0 (inclusive).

Image FormatBit DepthPixel FormatPixel TypeImage
RGBA16_SNORM4×16RGBASHORT✔️
RGBA8_SNORM4×8RGBABYTE✔️
RGB16_SNORM3×16RGBSHORT❌
RGB8_SNORM3×8RGBBYTE❌
RG16_SNORM2×16RGSHORT✔️
RG8_SNORM2×8RGBYTE✔️
R16_SNORM1×16REDSHORT✔️
R8_SNORM1×8REDBYTE✔️

Floating point buffers allow the attachment to store true floating point values. They are only available with larger than default precision due to the increased storage needed for floating point values. However, they offer a significantly larger range of values, allowing the storing of HDR values.

Detailed explanation: OpenGL Wiki - Small Float Formats

Image FormatBit DepthPixel FormatPixel TypeImage
RGBA32F4×32RGBAFLOAT✔️
RGBA16F4×16RGBAHALF_FLOAT✔️
RGB32F3×32RGBFLOAT❌
RGB16F3×16RGBHALF_FLOAT❌
R11F_G11F_B10F11/11/10RGBUNSIGNED_INT_10F_11F_11F_REV*✔️
RGB9_E5SpecialRGBUNSIGNED_INT_5_9_9_9_REV*❌
RG32F2×32RGFLOAT✔️
RG16F2×16RGHALF_FLOAT✔️
R32F1×32REDFLOAT✔️
R16F1×16REDHALF_FLOAT✔️
*Requires Iris 1.8+

The RGB9_E5 format uses a 5-bit exponent for all three terms (R, G, and B), where each component has a 9 bit mantissa. This allows for significantly more precision than R11F_G11F_B10F, which only has 6 to 5 bits of precision per component. However, R11F_G11F_B10F has individual exponents for each component. In both cases, there is no sign bit, so these formats cannot store negative values.

Bit DepthSigned MinSigned MaxUnsigned Max
32-214748364821474836474294967295
10-5125111023
16-327683276765535
8-128127255
2-213

Unsigned integral buffers store unsigned integers, which will not be interpreted as negative values (although they can be cast to signed integers after being read). As such they do not directly allow the storage of negative integers, but have double the range of their signed cousins in the positive domain.

Image FormatBit DepthPixel FormatPixel TypeImage
RGBA32UI4×32RGBA_INTEGERUNSIGNED_INT✔️
RGBA16UI4×16RGBA_INTEGERUNSIGNED_SHORT✔️
RGBA8UI4×8RGBA_INTEGERUNSIGNED_BYTE✔️
RGB10_A2UI*10/10/10/2RGBA_INTEGERUNSIGNED_INT_2_10_10_10_REV✔️
RGB32UI3×32RGB_INTEGERUNSIGNED_INT❌
RGB16UI3×16RGB_INTEGERUNSIGNED_SHORT❌
RGB8UI3×8RGB_INTEGERUNSIGNED_BYTE❌
RG32UI2×32RG_INTEGERUNSIGNED_INT✔️
RG16UI2×16RG_INTEGERUNSIGNED_SHORT✔️
RG8UI2×8RG_INTEGERUNSIGNED_BYTE✔️
R32UI1×32RED_INTEGERUNSIGNED_INT✔️
R16UI1×16RED_INTEGERUNSIGNED_SHORT✔️
R8UI1×8RED_INTEGERUNSIGNED_BYTE✔️
*Requires Iris 1.8+

Signed integral buffers store signed integers, just like the tin says. These are standard two’s complement integers, which means they can store negative values.

Image FormatBit DepthPixel FormatPixel TypeImage
RGBA32I4×32RGBA_INTEGERINT✔️
RGBA16I4×16RGBA_INTEGERSHORT✔️
RGBA8I4×8RGBA_INTEGERBYTE✔️
RGB32I3×32RGB_INTEGERINT❌
RGB16I3×16RGB_INTEGERSHORT❌
RGB8I3×8RGB_INTEGERBYTE❌
RG32I2×32RG_INTEGERINT✔️
RG16I2×16RG_INTEGERSHORT✔️
RG8I2×8RG_INTEGERBYTE✔️
R32I1×32RED_INTEGERINT✔️
R16I1×16RED_INTEGERSHORT✔️
R8I1×8RED_INTEGERBYTE✔️

The shader loader supports some additional pixel types, not directly associated with specific image formats, that can be used when loading raw custom textures. See the OpenGL Wiki for more information about these.

Pixel Type
UNSIGNED_BYTE_3_3_2
UNSIGNED_SHORT_5_6_5
UNSIGNED_SHORT_4_4_4_4
UNSIGNED_SHORT_5_5_5_1
UNSIGNED_INT_8_8_8_8
UNSIGNED_INT_8_8_8_8_REV
UNSIGNED_INT_10_10_10_2