GAMES104

Lookup Table

Posted by LudoArt on May 21, 2022

Lookup Table

Lookup Table

Lookup Table,简写为LUT,可以将输入的颜色,通过查表的方式,映射到另一种颜色上。

颜色表示为三个分量值,其中每个分量决定了颜色所包含的红色、绿色或蓝色的量,如图所示的立方体可以表示屏幕上显示的任何颜色。

image-20220521212414651

我们可以由蓝色轴对整个立方体进行切片,并将切片并排放在二维网格中。如将立方体切成16个切片,每个切片都包含了一个16*16像素的网格,如图所示:

image-20220521212814859

对于16个切片,从左到右,每个切片中包含的蓝色越来越多;对于每个切片,从左到右,红色越来越多,从上到下,绿色越来越多。即左上角的RGB值为(0, 0, 0),右下角的RGB值为(1, 1, 1)。

查找颜色

因为LUT的主要思想是输入某个颜色值,找到其在图上对应位置的颜色值,所以主要的问题在于如何定位某个颜色值在图上的位置,对于16个切片来说,红色和绿色的值是一致的,唯一不同的就是蓝色值。

所以第一步,我们可以先获取到红色和绿色在某个切片内的位置(r_offset和g_offset),将输入的R和G值重映射到0-15上:

#define MAXCOLOR 15.0
#define COLORS 16.0
#define WIDTH 256.0
#define HEIGHT 16.0

vec4 px = texture2D(original, var_texcoord0.xy); // 获取输入的颜色值

float r_offset = px.r * MAXCOLOR / WIDTH; // 计算红色的偏移量
float g_offset = px.g * MAXCOLOR / COLORS; // 计算绿色的偏移量

对于蓝色来说,由于要计算当前处于哪一个切片当中,必须取一个整数值,则有可能产生较大的误差,所以此处用一个插值来解决:

float b_offset_left = floor(px.b * MAXCOLOR) * COLORS / WIDTH; // 向下取整
float b_offset_right = ceil(px.b * MAXCOLOR) * COLORS / WIDTH; // 向上取整

vec4 color_left = texture(lut, vec2(b_offset_left + r_offset, g_offset)); // 对左边的切片采样,取左值
vec4 color_right = texture(lut, vec2(b_offset_right + r_offset, g_offset)); // 对右边的切片采样,取右值

vec4 graded_color = mix(color_left, color_right, fract(px.b * MAXCOLOR)); // 由px.b * MAXCOLOR的小数部分决定该如何混合两种颜色

这个时候便得到了查表后得到的最终颜色值:graded_color。