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

Started by
4 comments, last by smasherprog 13 years ago
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?
Advertisement
noone has any ideas?
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.
Wisdom is knowing when to shut up, so try it.
--Game Development http://nolimitsdesigns.com: Reliable UDP library, Threading library, Math Library, UI Library. Take a look, its all free.
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


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;
}


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"?
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 LogLUV, RGBM, etc
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.
Wisdom is knowing when to shut up, so try it.
--Game Development http://nolimitsdesigns.com: Reliable UDP library, Threading library, Math Library, UI Library. Take a look, its all free.

This topic is closed to new replies.

Advertisement