<p>In GLSL use frac to get the fractional part:</p>
<pre><code>   float x=1.02;
   x = frac(x);  // x==0.02 (in C++ use the modf function)
</code></pre>
<p>Multiply the fractional part by the max of the accuracy you want:</p>
<pre><code>  float accuracy=255;  // 8 bits of accuracy (65535 for 16 bits)
  x*=255;  // x==5.12
</code></pre>
<p>Throw away the fractional part:</p>
<pre><code>  int y = round(x);  // y == 5;
</code></pre>
<p>The value is ready to be stored in whatever 8 bit format is need. Such as a texture, or vertex attributes, etc.</p>
<p>To recover the fraction:</p>
<pre><code>float x = (float)value / 255.0;  // 5.0/255.0 == 0.01953125
</code></pre>
<p>This gives unsigned values between 0 and 1. A similar approach can be used for values between -1 and 1.</p>
<p>Precision is lost to the 8 bit encoding. But like mentioned in the comments that same can be done with 16 bit numbers.</p>
<p>If the values need to be stored in a texture then there are image formats just for this such as UNORM and SNORM. The GPU does the math for these formats when they are read from the texture.</p>
<p>The specs for the different API's provide guidelines on the expected values. The <a href="https://registry.khronos.org/vulkan/specs/1.0/html/vkspec.html#fundamentals-fixedconv" rel="nofollow noreferrer">vulkan spec</a> has something close to a function and a good explanation of the conversions it expects.</p>

CC BY-SA 4.0
2022-10-29T19:03:48.223Z
Small nitpick, when converting to int you should use `round()` or similar, rather than a simple cast which truncates.
Nathan Reed
CC BY-SA 4.0
2022-10-29T18:48:11.580Z
2022-10-29T21:00:34.863Z
2022-10-29T21:00:34.863Z
pmw1234
<p>I am compressing a string of data in the formats of float. The current approach is throwing away eight bits in the integer part as my float is strictly within [0,1].</p>
<p>I wonder how I could do this.</p>

CC BY-SA 4.0
2022-10-27T07:57:35.513Z
Are you talking about IEEE floats?  If the numbers are [0,1], then there are no integer bits per se.  You could get rid of the sign bit, as that'd be constant, but it's not much of a saving.
Simon F
CC BY-SA 4.0
2022-10-27T17:37:11.780Z
For [0,1] values an easier approach to compression is to convert it to a fixed-point representation with however many bits you want (8 or 16, for example).
Nathan Reed
<texture>
compressing my [0,1] floats by throwing away the integer part
Lilylilyren
# compressing my [0,1] floats by throwing away the integer part

(Asked by: username_0 on 2022-10-27)

I am compressing a string of data in the formats of float. The current approach is throwing away eight bits in the integer part as my float is strictly within [0,1].

I wonder how I could do this.

**Tags:** texture

> **Comments:**
> **username_1**: Are you talking about IEEE floats?  If the numbers are [0,1], then there are no integer bits per se.  You could get rid of the sign bit, as that'd be constant, but it's not much of a saving.  
> **username_2**: For [0,1] values an easier approach to compression is to convert it to a fixed-point representation with however many bits you want (8 or 16, for example).  

---

## 1 answers

### Answer by username_3 on 2022-10-29. Score: 1

In GLSL use frac to get the fractional part:

```
   float x=1.02;
   x = frac(x);  // x==0.02 (in C++ use the modf function)

```

Multiply the fractional part by the max of the accuracy you want:

```
  float accuracy=255;  // 8 bits of accuracy (65535 for 16 bits)
  x*=255;  // x==5.12

```

Throw away the fractional part:

```
  int y = round(x);  // y == 5;

```

The value is ready to be stored in whatever 8 bit format is need. Such as a texture, or vertex attributes, etc.

To recover the fraction:

```
float x = (float)value / 255.0;  // 5.0/255.0 == 0.01953125

```

This gives unsigned values between 0 and 1. A similar approach can be used for values between -1 and 1.

Precision is lost to the 8 bit encoding. But like mentioned in the comments that same can be done with 16 bit numbers.

If the values need to be stored in a texture then there are image formats just for this such as UNORM and SNORM. The GPU does the math for these formats when they are read from the texture.

The specs for the different API's provide guidelines on the expected values. The [vulkan spec](https://registry.khronos.org/vulkan/specs/1.0/html/vkspec.html#fundamentals-fixedconv) has something close to a function and a good explanation of the conversions it expects.

> **Comments:**
> **username_2**: Small nitpick, when converting to int you should use `round()` or similar, rather than a simple cast which truncates.  

---

