2011年1月20日 星期四

如何利用RGBA_8888,壓縮浮點RGBA [0.0, 1.0]數值

Dear All:
這各部分是很久以前遇到的問題,問題是:“要將GPU所算出的rgba三原色,存入一張dds圖檔,當成Lightmap使用”,很直覺的問題在如何將[0.0, 1.0]的數值存到8bit中?其實這不算什麼新鮮的問題,翻開HDR的歷史,過去舊時代的GPU(如Ps2、XBox)因沒有支援浮點格式的RenderTarget,所以必須想辦法將浮點數壓縮存在一張整數格式的RenderTarget上,來達到HDR的效果,來看看我找到的方法吧!

//這裡將[0.0, 20.0]的數值壓縮到[0.0, 1.0]之間:
Vector4& color = vTempTexture[ py * pCurTexture->Width() + px ];
color *= (1.0f / 20.0f);

//找出RGB最大者,做為將來的除數:
float fA = max( max( color.r, color.g ), max( color.b, 1e-6 ) );
if( fA >= 1 ) fA = 1; else if( fA <= 0 ) fA = 0;

//將fA存在Alpha channel,並將所有RGB用fA以除之:
Vector4 rgbm;
rgbm.a = fA;
rgbm.a = ceil( rgbm.a * 255.0f ) / 255.0f;
rgbm.r = color.r / rgbm.a;
rgbm.g = color.g / rgbm.a;
rgbm.b = color.b / rgbm.a;

//還原回整數表示:
int iValueA = (int)(rgbm.a * 255.0f);
int iValueR = (int)(rgbm.r * 255.0f);
int iValueG = (int)(rgbm.g * 255.0f);
int iValueB = (int)(rgbm.b * 255.0f);

if( iValueA > 255 ) iValueA = 255;
if( iValueR > 255 ) iValueR = 255;
if( iValueG > 255 ) iValueG = 255;
if( iValueB > 255 ) iValueB = 255;

//存入貼讀中:
d3dPixel = ( iValueA << 24 ) | ( iValueR << 16 ) | ( iValueG << 8 ) | iValueB;
而在Shader Code使用這張貼時,記得還原壓縮RGB數值:
diffuseLightmap = lightmap.rgb * lightmap.a * 20;

其實說穿了,這各方法就是針對每一各Pixel找三各channel中的最大值去做壓縮,當然還有另一種方式為per-texture的,很直覺得它是找出貼圖中所有的Pixel裡channel數值最大者進行壓縮,也不失是依各好方法!!

以上的說明希望對"未來的我" or "正在閱讀的你"有幫助,謝謝!!

沒有留言:

張貼留言

LinkWithin

Related Posts Plugin for WordPress, Blogger...