There was one solution that followed the right path, but failed in the implementation.

For reference, here are the links I found in the process:

http://www.gamedev.n...xture-and-glsl/

http://www.gamedev.n...gb-in-a-shader/

http://www.gamedev.n...a-byte-texture/

Implementing this with integer logic is rather straight forward:

[source lang="cpp"]// Encode:R = value &0xff;G = (value >> 8) & 0xff;B = (value >> 16) & 0xff;// Decode:value = (B << 16) | (G << 8) | R;[/source]

The trick turns then into converting that to floating point logic that can be used in GLSL. Well, here is the solution to encode it in 16 bits:

[source lang="cpp"]// Encode:const float max16int = 256.0 * 256.0 - 1.0;value *= max16int;vec2 result = floor(value / vec2(256.0, 1.0));result.g -= result.r * 256.0;result /= 255.0;// Decodeconst float max16int = 256.0 * 256.0 - 1.0;float result = 255.0 * dot(value, vec2(256.0, 1.0)) / max16int;[/source]

The same idea can be used to encode the value in 24 bits:

[source lang="cpp"]// Encode:const float max24int = 256.0 * 256.0 * 256.0 - 1.0;value *= max24int;vec3 result = floor(value / vec3(256.0 * 256.0, 256.0, 1.0));result.gb -= result.rg * 256.0;result /= 255.0;// Decode:const float max24int = 256.0 * 256.0 * 256.0 - 1.0;float result = 255.0 * dot(value, vec3(256.0 * 256.0, 256.0, 1.0)) / max24int;[/source]

Find attached the results of the same scene where the encoded depth is used as the fragment color. One uses RG, the other RGB.

Notice how the plane color seems to repeat in a color band fashion. The farthest red is (255, 3, 0), the next one is (254, 3, 0), then (253, 3, 0). The algorithms also encode 1 as all 1s, so no values are wasted.

As a bonus, I include a greenscale version of the scene that uses a very simple sort of encoding that roughly makes the input value linear (again, just roughly), using the following code:

[source lang="cpp"]result = pow(value, 128.0);[/source]

**NOTE:**This way of encoding values does not play nicely with filtering. As an example consider the RG encoding of 0.5 (which cannot be represented exactly) and that of linearly interpolating between 0 and 1 (byte values are used for clarity):

0.5: (127, 255)

0.0: (0, 0)

1.0: (255, 255)

0.5 (interpolated): (127, 127)

The real encoding of 0.5 and the interpolation of it are close, yet off (by 128 in G). If "close" is good enough, then you may use interpolation.