0
\$\begingroup\$

There's solutions to convert float to RGBA but I would like to encode a float depth value in RGB format and save the three components in three separated unused alpha channels and recompose when needed. I prefer 24bit float because the decoded value is to be compared to regular 24+8 bit depthstencil buffer.

there's this code for float to RGBA (https://gamedev.net/forums/topic/684158-rgba-to-float-percision/5321338/)

vec4 pack(float depth)
{
   const vec4 bitSh = vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);
   const vec4 bitMsk = vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
   vec4 comp = fract(depth * bitSh);
   comp -= comp.xxyz * bitMsk;
   return comp;
 }

float unpack(vec2 pos)
{
   vec4 packedZValue = texture2D(shadow_map, pos); 
   const vec4 bitShifts = vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1);
   float shadow = dot(packedZValue , bitShifts); 
   return shadow;
}

I tried to change to vec3 by removing the first component as below but get weird results (see picture below).

Note: left panels are showing the alpha chanel were the depth is stored as 3 component (1rt = x, 3rd = y and 4th = z, second is something else) by default the alpha channel is 1 (so it appears white) as it is for depth buffer and I perform a alpha OP_MIN test to write new value as if it was comparison_less. So we can see something in panel 1/3 but in 4 it is still white suggesting that the z value is 1 or more.

vec3 pack(float depth)
{
   const vec3 bitSh = vec3(256.0 * 256.0, 256.0, 1.0);
   const vec3 bitMsk = vec3(0, 1.0 / 256.0, 1.0 / 256.0);
   vec3 comp = fract(depth * bitSh);
   comp -= comp.xyz * bitMsk;
   return comp;
 }

float unpack()
{
   vec3 packedZValue = float3(textureA.a, textureB.a, textureC.a); 
   const vec3 bitShifts = vec4(1.0 / (256.0 * 256.0), 1.0 / 256.0, 1);
   float shadow = dot(packedZValue , bitShifts); 
   return shadow;
}

enter image description here

\$\endgroup\$
2
  • 1
    \$\begingroup\$ What "weird results" do you get? \$\endgroup\$
    – Kevin
    Jun 4, 2022 at 0:45
  • \$\begingroup\$ I added a picture and some other informations for clarity \$\endgroup\$
    – philB
    Jun 7, 2022 at 8:06

1 Answer 1

1
\$\begingroup\$

Finally I change from RGB to RG encoding of depth with the code found here that is fine (https://blog.katastros.com/a?ID=00300-1312986b-8ead-4a41-8d1e-1845010de79a). Importantly I made a final test to have correct value for depth = 1 as the method seems not able to give full 1.0f. The code is recalled below with added the special depth =1 test in the depth decode part as well as a picture of the result.

encode :

 float2 FloatToRG(float v)
 {
    float2 kEncodeMul = float2(1.0f, 255.0f);
    float kEncodeBit = 1.0f/255.0f;
    float2 color = kEncodeMul*v;
    color = frac(color);
    color.x -= color.y * kEncodeBit;
    return color;
 }

decode

 //TexS is an int3
 float2 DRG = float2(textureA.Load(TexS).a, textureB.Load(TexS).a);
 float D = dot(DRG, float2(1.0f, 1.0f/255.0f));
 if ( D > 0.9999f ) D = 1;// needed to have correct value depth = 1

maybe there is a limit to this final test but it gives me what I need. enter image description here

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .