Reducing Texture Memory Usage by 2-channel Color Encoding | Cheney Shen

Technology blog

Reducing Texture Memory Usage by 2-channel Color Encoding

原理:

简单地说就是贴图一般所使用到的色域都很小,因此可以利用这个特征来减少表示texture的数据量。

These single-material textures often do not exhibit large color variety and contain a limited range of hues, while using a full range of brightness resulting from highlights and dark (e.g., shadowed), regions within the material surface.

 

基本做法就是传输亮度和饱和度

The method presented here follows these observations and aims to encode any given texture into two channels: one channel preserving full luminance information and the other one dedicated to hue/saturation encoding.

 

Texture Encoding Algorithm

 

编码就是三维映射到二维的过程,就是找出一个平面,使得所有的三维顶点到该平面的距离最小来保证误差最小。

Approximating this space with two channels effectively means that we have to find a surface (two-dimensional manifold) embedded within this unit cube that lies as close as possible to the set of texels from the source texture.

bgt_7_01

 

步骤:

1. 重估颜色空间

 

sRGB颜色值转到线性颜色空间。

RGB值对亮度的贡献的非线性和不同的,因此我们要赋予RGB不同的权重。

上面两步得到新的可以线性运算的三维空间坐标

bgt_7_02

然后在此基础上去计算平面。

点到平面距离:

bgt_7_03

所有点到平面距离的平方和

bgt_7_04

通过如下计算方法计算得到。参考 estimate_image 函数和书本。

2. 算出两个base的颜色向量

 

bgt_7_05

这里很简单如图:已知道 bc1(0,1,m)bc2(1,0,n)初始化以后利用平面的信息求的。见函数

find_components() 求解。

3. 亮度编码

 

公式:

bgt_7_06

4. 饱和度编码

 

bgt_7_07

四步走:首先获得三维点在平面的投影,然后就有(0,0,0)到该投影点的向量,另外还可以计算得到两个base颜色向量,让这个投影向量用两个基本颜色向量表示。最终再通过公式求的饱和度值。

 

Decoding Algorithm

这个很简单,就是也需要两个base颜色值和亮度混合参数,然后反解得到。

bgt_7_08

 

  • 实现:

 

vec3 estimate_image(BITMAP *src) :

整个拆成 rr, gg, bb, rg, rb, gb 六个分量。首先计算整个image的六个分量的均值。

然后暴力法遍历预设好的法线取值范围(例 n.xyz 在 0 到 100)

求出误差公示最小的法线值。

 

void stamp_color_probe(BITMAP *bmp):

这个是图片颜色预处理

 

编码:

BITMAP *encode_image(BITMAP *src,vec3 n):

平面法线normalize,并找出两个基本的颜色。

然后通过这两个基本颜色构建2d位置坐标系和对应的颜色坐标系。

接着创建输出bitmap,然后对于每一个输出mipmap的像素点:

获得RGB值

应用 gamma 2.0

计算 2D 坐标系下面的坐标位置和颜色

构建饱和度 float hue = -da/(db-da+0.00000001f);(da, db是2d坐标下的颜色值)

构建亮度  float lum = sqrt(c.dot(to_scale))

编码成 hue, lum 两个分量。

 

解码

BITMAP *decode_image(BITMAP *src,const vec3 &base_a,const vec3 &base_b):

初始化目标Bitmap对于它的每一个像素点

首先获得传过来的 hue, lum

解码颜色 vec3 c = base_a + (base_b-base_a)*hue;

解码亮度 float clum = 0.2126f*c.x + 0.7152f*c.y + 0.0722f*c.z;

应用 gamma 2.0 回到 sRGB 值

 


Post a Comment

Your email address will not be published. Required fields are marked *

  • Categories

  • Tags