把float編碼到RGBA8

編碼和解碼

單通道的float是32-bit,RGBA8也是,因此按說把float編碼到RGBA8的紋理中應該沒啥問題。很惋惜的是,不支持浮點紋理的硬件每每也不支持整數指令和位運算操做。因此在這裏須要有些限制。在網上搜了一下,最靠譜的應該是大牛Aras Pranckevičius(aras-p)多年前的帖子。他的作法能夠把[0, 1)範圍內的浮點數,僅僅用shader model 2的指令,就編碼到RGBA8。其實[0, 1)基本就夠用了,其餘的只要除個常數,讀取後乘回去就能夠了。編碼和解碼的函數很簡單:函數

float4 EncodeFloatRGBA(float v) 
{
     float4 enc = float4(1.0f, 255.0f, 65025.0f, 16581375.0f) * v; 
     enc = frac(enc); 
     enc -= enc.yzww * float4(1 / 255.0f, 1 / 255.0f, 1 / 255.0f, 0); 
     return enc; 

 float DecodeFloatRGBA(float4 rgba) 
{
     return dot(rgba, float4(1, 1 / 255.0f, 1 / 65025.0f, 1 / 16581375.0f)); 
}

這裏的65025和16581375其實就是255的平方和立方。(aras-p的原文有一處筆誤,把16581375寫成了160581375。)post

長啥樣編碼


用途spa

這個東西能用在什麼地方呢?流水線中目前有三處可能能夠用到的:3d

HDR post process

在HDR post process裏面,經過統計圖像來產生自適應亮度調整的時候,只用到了單通道的float16和float32紋理,因此這裏能夠用這個方法進行編碼。code

Depth

在Pre-depth的時候,也能夠把32-bit的depth編碼後存到RGBA8。blog

ESM

Exponential shadow map只須要用到一個通道,也能順利使用這個技巧。get

這些應用我之後都會有專門的帖子展開討論。it



相關文章
相關標籤/搜索