Packing 3 unorms in 16 bit uint in shader

Started by
2 comments, last by B_old 14 years, 1 month ago
I'm toying with the idea to not only save the specular factor but the entire specular color in my g-buffer. I'd like to pack the color in 16 bits though. Here's what I came up with:

float pack(float3 v)
{
    float3 t = floor(v * 31.f + 0.5f);

    return t.x * 1024.f + t.y * 32.f + t.z;
}


float3 unpack(float v)
{
    float ip;
    float fp = modf(v / 1024.f, ip);

    float x = ip;

    fp = modf(fp * 32.f, ip);

    float y = ip;

    float z = fp * 32.f;

    return float3(x, y, z) / 31.f;
}


I haven't had the time yet to try the entire thing, but I'm curious what you think. Do you think it is worth it? Could the conversion be made more efficient? I tested the code in C++ and quickly translated it to HLSL for the post, so it be somewhat wrong, but should work in principle. [Edited by - B_old on March 22, 2010 7:01:01 AM]
Advertisement
1. before you accumulate your values, you need to remove the fractional part and clamp/saturate the channels.

2. I think even if you set an uint16 rendertarget, the output range is 0.0-1.0, so you'd need to work with 1024.f/65536.f

3. 16bit can look kind of bad on the output target (lot of banding, especially when you go for HDR). I would suggest you to use some different encoding like YUV, YCbCr or YCoCg. Donate 8bits for luminance and the quality should be better.
Thanks for the reply!
Quote:Original post by Krypt0n
1. before you accumulate your values, you need to remove the fractional part and clamp/saturate the channels.

I don't understand. The input is supposed be in the 0-1 range and I use floor before I add the individual values up. Not what you mean?

Quote:Original post by Krypt0n
2. I think even if you set an uint16 rendertarget, the output range is 0.0-1.0, so you'd need to work with 1024.f/65536.f

Hm, ok. What is the difference to a unorm16 target then?

Quote:Original post by Krypt0n
3. 16bit can look kind of bad on the output target (lot of banding, especially when you go for HDR). I would suggest you to use some different encoding like YUV, YCbCr or YCoCg. Donate 8bits for luminance and the quality should be better.

That might be a problem, but on the other hand I am hoping it won't be that noticeable because it only is the specular color.

I've tried to implement it in HLSL now and as far as I can tell it works. (I actually did have a problem with packing the specular exponent if its very small. I haven't found out what happens but it is not really an issue right now.)

I'm wondering right now whether my choice of render target 2xUint16 is wise. In D3D10+ there are typeless formats. How do you use them properly and what is the advantage?
In case someone cares, my questions from the previous post still stand. :)

This topic is closed to new replies.

Advertisement