Sign in to follow this  
mancubit

Enhancing precision of 8bit RGB channels by utilizing the 8bit Alpha channel

Recommended Posts

mancubit    536
Although the topic name says it all: i am searching for a good way to improve precision of RGB channels (Rendertarget is a DXGI_FORMAT_R8G8B8A8_UNORM) by utilizing the 8bits of the remaining alpha channel. I guess thats what the DXGI_FORMAT_R10G10B10A2_UNORM does. But what if i am stuck to the 8bit per channel, how can i achieve higher precision? The only method i can think of, is to "assign" each rgb-component 2 bits of the alpha channel by doing some bit shift tricks, but i dont know how to do it exactly..

any suggestions?

Share this post


Link to post
Share on other sites
smasherprog    568
It would work if you used the Load Function. You could not use any filtering because that would destroy the information due to blending. So, if you are ok with no filtering, then you can use some bit shifting to get the extra precision, but you would be better off using the 1010102 format.

Share this post


Link to post
Share on other sites
mancubit    536
i read deeper into bit operators and finally got something that seems to work. For anyone who needs something like that, here are my encode/decode functions

[code]
float4 encode10(float3 value)
{
// encode components of value to 10 bits by utilizing the alpha channel
int ir = value.r * 1024;
int ig = value.g * 1024;
int ib = value.b * 1024;

int a = 0;

a = (ir & 3);
a = (a << 2 ) | (ig & 3);
a = (a << 2 ) | (ib & 3);

int hr = (ir & 1020) >> 2;
int hg = (ig & 1020) >> 2;
int hb = (ib & 1020) >> 2;

float4 result;
result.r = (float)hr / 256.0f;
result.g = (float)hg / 256.0f;
result.b = (float)hb / 256.0f;
result.a = (float)a / 256.0f;

return result;
}

float3 decode10(float4 encoded)
{
int hr = encoded.r * 256.0f;
int hg = encoded.g * 256.0f;
int hb = encoded.b * 256.0f;
int a = encoded.a * 256.0f;

int or = (hr << 2) | (a >> 4);
int og = (hg << 2) | ((a >> 2) & 3);
int ob = (hb << 2) | (a & 3);

float3 result;
result.r = (float)or / 1024.0f;
result.g = (float)og / 1024.0f;
result.b = (float)ob / 1024.0f;

return result;
}
[/code]

edit: ok i guess now i have some troubles with linear filtering? hmm..that makes this solution kind of unusable for me...
is there anything i can do? i don't think, it's possible to overcome this problem, is it?

@smasherprog:
thanks for your answer, but what do you mean with "the load function"?

Share this post


Link to post
Share on other sites
Hodgman    51342
Packing higher-precision colour data into an RGBA texture was very common on platforms like the Xbox(original), PS2, Wii, which didn't support "high precision" textures... Usually an alternate colour space would be used, such as [url="http://realtimecollisiondetection.net/blog/?p=15"]LogLUV[/url], [url="http://graphicrants.blogspot.com/2009/04/rgbm-color-encoding.html"]RGBM[/url], etc

Share this post


Link to post
Share on other sites
smasherprog    568
You have to do your own filtering on the texture using multiple load()'s in the pixel shader. Instead of using Sample() to retrieve a pixel from the texture. But, bit-wise operators weren't available till 4.0, so you should use the 1010102 texture for the increased resolution because hardware texture filtering is better than the manual filtering you will have to do.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this