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;
}
Packing 3 unorms in 16 bit uint in shader
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:
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]
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.
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!
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?
Hm, ok. What is the difference to a unorm16 target then?
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.
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. :)
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
Popular Topics
Advertisement