Skip to content

Commit

Permalink
Merge pull request #331 from Luracasmus/main
Browse files Browse the repository at this point in the history
feat/mod/fix: buffers: Texture/Image Format Rewrite
  • Loading branch information
ninjamike1211 authored Nov 1, 2024
2 parents adef2f6 + ebff53a commit a30d6f3
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 131 deletions.
2 changes: 1 addition & 1 deletion src/content/docs/reference/Buffers/colortex.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Additionally, you can read and write to the first 6 colortex buffer in Optifine
These buffers default to the display resolution, although this can be configured with the [`size.buffer`](/reference/shadersproperties/rendering#sizebuffer) define in shaders.properties. However, changing the buffer size will prevent any [`gbuffer`](/reference/programs/gbuffers) program from writing to the texture.

#### Buffer format/precision
All buffers default to `RGBA` format (which is `RGBA8` on most systems), but this can be configured as described in the [Texture Formats](/reference/buffers/texture_format) section.
All buffers default to `RGBA` format (which is `RGBA8` on most systems), but this can be configured as described in the [Texture Formats](/reference/buffers/image_format) section.

#### Buffer clear
By default all buffers clear their values after each frame to solid black (all 0s including alpha), except `colortex0` which clears to the [`fogColor`](/reference/uniforms/rendering#fogcolor) with 1.0 alpha, and `colortex1` which clears to solid white (all 1s including alpha). This clearing behavior can be configured with the [`colortexNClear`](/reference/constants/buffer_clear) directive, and the clear color can be configured with the [`colortexNClearColor`](/reference/constants/buffer_clear_color) directive.
Expand Down
6 changes: 3 additions & 3 deletions src/content/docs/reference/Buffers/custom_images.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ To declare a custom image, use the following in shaders.properties:
Replace:
- `<imageName>` with the variable name of the image
- `<samplerName>` with the variable name of the sampler
- `<format>` with the [pixel format](/reference/buffers/texture_format) of the image (see "Pixel Formats" section)
- `<internalFormat>` with the [texture format](/reference/buffers/texture_format) of the image (see "Texture Format" section)
- `<pixelType>` with the [pixel type](/reference/buffers/texture_format) of the image (see "Pixel Types" section)
- `<format>` with the [pixel format](/reference/buffers/image_format) of the image (see "Pixel Formats" section)
- `<internalFormat>` with the [texture format](/reference/buffers/image_format) of the image (see "Texture Format" section)
- `<pixelType>` with the [pixel type](/reference/buffers/image_format) of the image (see "Pixel Types" section)
- `<shouldClearOnNewFrame>` with `true` to clear the image after each frame, or `false` to retain data between frames
- `<isRelative>` with `true` to make the image dimensions relative to the screen dimensions, or `false` to make the dimensions absolute
- `<relativeX/absoluteX>` with the relative (floating point) or absolute (integer) size in the x dimension
Expand Down
6 changes: 3 additions & 3 deletions src/content/docs/reference/Buffers/custom_textures.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ Raw textures can be loaded from the shader files, similarly to image files. Howe
texture.<stage>.<bufferName> = <path> <type> <internalFormat> <dimensions> <pixelFormat> <pixelType>
```
- Replaec `<type>` with one of the following: `TEXTURE_1D`, `TEXTURE_2D`, `TEXTURE_3D`, or `TEXTURE_RECTANGLE`.
- Replace `<internalFormat>` with the [texture format](/reference/buffers/texture_format).
- Replace `<internalFormat>` with the [texture format](/reference/buffers/image_format).
- Replace `<dimensions>` with the fixed size dimensions of the texture (the number of components depends on the type).
- Replace `<pixelFormat>` with the pixel format described in the "Pixel Formats" section of the [texture format section](/reference/buffers/texture_format).
- Replace `<pixelType>` with the pixel type described in the "Pixel Types" section of the [texture format section](/reference/buffers/texture_format).
- Replace `<pixelFormat>` with the pixel format described in the "Pixel Formats" section of the [texture format section](/reference/buffers/image_format).
- Replace `<pixelType>` with the pixel type described in the "Pixel Types" section of the [texture format section](/reference/buffers/image_format).


### PBR textures
Expand Down
152 changes: 152 additions & 0 deletions src/content/docs/reference/Buffers/image_format.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
---
title: Image Format
description: Available image formats for buffers.
sidebar:
label: Image Format
order: 4
---

import { Aside } from '@astrojs/starlight/components';

Color attachments such as [colortex](/reference/buffers/colortex) and [shadowcolor](/reference/buffers/shadowcolor) buffers, as well as custom [images](/reference/buffers/custom_images/) and [textures](/reference/buffers/custom_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](/reference/constants/buffer_format) directive.

The available image formats and their meanings are described below.

## Normalized

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.

Detailed explanation: [OpenGL Wiki - Normalized Integer](https://www.khronos.org/opengl/wiki/Normalized_Integer)

### Unsigned Normalized Formats

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

| Image Format | Bit Depth | Pixel Format | Pixel Type | Image | Requirements |
| ------------ | ---------- | ------------ | ----------------------------- | ----- | -------------------------------------------------------------------------------------------------------------------- |
| `RGBA16` | 4×16 | `RGBA` | `UNSIGNED_SHORT` | ✔️ | |
| `RGBA8` | 4×8 | `RGBA` | `UNSIGNED_BYTE` | ✔️ | |
| `RGB10_A2` | 10/10/10/2 | `RGBA` | `UNSIGNED_INT_2_10_10_10_REV` | ✔️ | |
| `RGBA4`* | 4×4 | `RGBA` | `UNSIGNED_SHORT_4_4_4_4_REV` || OpenGL 4.2+ |
| `GL_RGB5_A1` | 5/5/5/1 | `RGBA` | `UNSIGNED_SHORT_1_5_5_5_REV` || OpenGL 4.2+ |
| `RGB16` | 3×16 | `RGB` | `UNSIGNED_SHORT` || |
| `RGB8` | 3×8 | `RGB` | `UNSIGNED_BYTE` || |
| `RGB565`* | 5/6/5 | `RGB` | `UNSIGNED_SHORT_5_6_5_REV` || OpenGL 4.1+ or [ARB_ES2_compatibility](https://registry.khronos.org/OpenGL/extensions/ARB/ARB_ES2_compatibility.txt) |
| `RG16` | 2×16 | `RG` | `UNSIGNED_SHORT` | ✔️ | |
| `RG8` | 2×8 | `RG` | `UNSIGNED_BYTE` | ✔️ | |
| `R16` | 16 | `RED` | `UNSIGNED_SHORT` | ✔️ | |
| `R8` | 8 | `RED` | `UNSIGNED_BYTE` | ✔️ | |
| `RGBA2`* | 4×2 | `RGBA` | || |
| `R3_G3_B2` | 3/3/2 | `RED` | `UNSIGNED_BYTE_2_3_3_REV` || |

*Requires Iris 1.8+

### Signed Normalized Formats

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

| Image Format | Bit Depth | Pixel Format | Pixel Type | Image |
| -------------- | --------- |------------- | ---------- | ----- |
| `RGBA16_SNORM` | 4×16 | `RGBA` | `SHORT` | ✔️ |
| `RGBA8_SNORM` | 4×8 | `RGBA` | `BYTE` | ✔️ |
| `RGB16_SNORM` | 3×16 | `RGB` | `SHORT` ||
| `RGB8_SNORM` | 3×8 | `RGB` | `BYTE` ||
| `RG16_SNORM` | 2×16 | `RG` | `SHORT` | ✔️ |
| `RG8_SNORM` | 2×8 | `RG` | `BYTE` | ✔️ |
| `R16_SNORM` | 16 | `RED` | `SHORT` | ✔️ |
| `R8_SNORM` | 8 | `RED` | `BYTE` | ✔️ |

## Floating Point

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](https://www.khronos.org/opengl/wiki/Small_Float_Formats)

### Floating Point Formats

| Image Format | Bit Depth | Pixel Format | Pixel Type | Image |
| ---------------- | -------------------------------------------------------------------------- | ------------ | -------------------------------- | ----- |
| `RGBA32F` | 4×32 | `RGBA` | `FLOAT` | ✔️ |
| `RGBA16F` | 4×16 | `RGBA` | `HALF_FLOAT` | ✔️ |
| `RGB32F` | 3×32 | `RGB` | `FLOAT` ||
| `RGB16F` | 3×16 | `RGB` | `HALF_FLOAT` ||
| `R11F_G11F_B10F` | 11/11/10 | `RGB` | `UNSIGNED_INT_10F_11F_11F_REV`* | ✔️ |
| `RGB9_E5` | [Special](https://www.khronos.org/opengl/wiki/Small_Float_Formats#RGB9_E5) | `RGB` | `5_9_9_9_REV`* ||
| `RG32F` | 2×32 | `RG` | `FLOAT` | ✔️ |
| `RG16F` | 2×16 | `RG` | `HALF_FLOAT` | ✔️ |
| `R32F` | 32 | `RED` | `FLOAT` | ✔️ |
| `R16F` | 16 | `RED` | `HALF_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.

## Integral

| Bit Depth | Signed Min | Signed Max | Unsigned Max |
| --------- | ----------- | ---------- | ------------ |
| 32 | -2147483648 | 2147483647 | 4294967295 |
| 10 | -512 | 511 | 1023 |
| 16 | -32768 | 32767 | 65535 |
| 8 | -128 | 127 | 255 |
| 2 | -2 | 1 | 3 |

### Unsigned Integral Formats

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 Format | Bit Depth | Pixel Format | Pixel Type | Image |
| ------------- | ---------- | -------------- | ----------------------------- | ----- |
| `RGBA32UI` | 4×32 | `RGBA_INTEGER` | `UNSIGNED_INT` | ✔️ |
| `RGBA16UI` | 4×16 | `RGBA_INTEGER` | `UNSIGNED_SHORT` | ✔️ |
| `RGBA8UI` | 4×8 | `RGBA_INTEGER` | `UNSIGNED_BYTE` | ✔️ |
| `RGB10_A2UI`* | 10/10/10/2 | `RGBA_INTEGER` | `UNSIGNED_INT_2_10_10_10_REV` | ✔️ |
| `RGB32UI` | 3×32 | `RGB_INTEGER` | `UNSIGNED_INT` ||
| `RGB16UI` | 3×16 | `RGB_INTEGER` | `UNSIGNED_SHORT` ||
| `RGB8UI` | 3×8 | `RGB_INTEGER` | `UNSIGNED_BYTE` ||
| `RG32UI` | 2×32 | `RG_INTEGER` | `UNSIGNED_INT` | ✔️ |
| `RG16UI` | 2×16 | `RG_INTEGER` | `UNSIGNED_SHORT` | ✔️ |
| `RG8UI` | 2×8 | `RG_INTEGER` | `UNSIGNED_BYTE` | ✔️ |
| `R32UI` | 32 | `RED_INTEGER` | `UNSIGNED_INT` | ✔️ |
| `R16UI` | 16 | `RED_INTEGER` | `UNSIGNED_SHORT` | ✔️ |
| `R8UI` | 8 | `RED_INTEGER` | `UNSIGNED_BYTE` | ✔️ |

*Requires Iris 1.8+

### Signed Integral Formats

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 Format | Bit Depth | Pixel Format | Pixel Type | Image |
| ------------ | --------- | -------------- | ---------- | ----- |
| `RGBA32I` | 4×32 | `RGBA_INTEGER` | `INT` | ✔️ |
| `RGBA16I` | 4×16 | `RGBA_INTEGER` | `SHORT` | ✔️ |
| `RGBA8I` | 4×8 | `RGBA_INTEGER` | `BYTE` | ✔️ |
| `RGB32I` | 3×32 | `RGB_INTEGER` | `INT` ||
| `RGB16I` | 3×16 | `RGB_INTEGER` | `SHORT` ||
| `RGB8I` | 3×8 | `RGB_INTEGER` | `BYTE` ||
| `RG32I` | 2×32 | `RG_INTEGER` | `INT` | ✔️ |
| `RG16I` | 2×16 | `RG_INTEGER` | `SHORT` | ✔️ |
| `RG8I` | 2×8 | `RG_INTEGER` | `BYTE` | ✔️ |
| `R32I` | 32 | `RED_INTEGER` | `INT` | ✔️ |
| `R16I` | 16 | `RED_INTEGER` | `SHORT` | ✔️ |
| `R8I` | 8 | `RED_INTEGER` | `BYTE` | ✔️ |

## Additional Pixel Types

The shader loader supports some additional pixel types, not directly associated with specific image formats, that can be used when loading [raw custom textures](https://shaders.properties/reference/buffers/custom_textures/#texturestagebuffername--path-type-internalformat-dimensions-pixelformat-pixeltype). See the [OpenGL Wiki](https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_type) 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` |

## Further Reading
* [OpenGL Wiki - Image Format](https://www.khronos.org/opengl/wiki/Image_Format)
2 changes: 1 addition & 1 deletion src/content/docs/reference/Buffers/shadowcolor.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Additionally, you can read and write to `shadowcolor0` and `shadowcolor1` using
These buffers default to the shadow pass resolution, which can be controlled with the `shadowMapResolution` constant.

#### Buffer format/precision
These buffers default `RGBA` format (which defaults to `RGBA8` on most systems), but this can be configured as described in the [Texture Formats](/reference/buffers/texture_format) section.
These buffers default `RGBA` format (which defaults to `RGBA8` on most systems), but this can be configured as described in the [Texture Formats](/reference/buffers/image_format) section.

#### Buffer clear
By default these buffers clear their values after each frame to solid white (all 1s including alpha) This clearing behavior can be configured with the [`shadowcolorNClear`](/reference/constants/buffer_clear) directive, and the clear color can be configured with the [`shadowcolorNClearColor`](/reference/constants/buffer_clear_color) directive.
Expand Down
Loading

0 comments on commit a30d6f3

Please sign in to comment.