1-调色ColorGrading
又开了个新坑,主要是给目前碰到的图形学算法(主渲染向)做一个类似索引的功能。
本文将介绍调色ColorGrading的原理,并在GAMES104作业里实现这个后处理算法。
原理
有关ColorGrading的介绍详见GAMES104相关文章。
如图,要想实现ColorGrading效果得通过LUT和片段着色器。对于处理前画面的每个像素:
- 根据它的RGB在LUT中查找对应的位置;
- 根据位置读取LUT中对应的颜色值;
- 使用读取的颜色值输出。
但早期着色器语言(如OpenGL ES 2.0)不支持3D纹理,因此需要将3D的LUT拆分成2D的,通过切分它的Z轴(即蓝色轴)实现。
为了查找2D的LUT,需要用蓝色通道值计算在第几个格子里采样,公式如下: \[ \nonumber cell = \left \lfloor{B \times (N - 1)} \right \rfloor \] 其中\(B\)是在[0, 1]内的蓝色通道值,\(N\)是2D LUT的格子总数。知道要查找哪个格子后,就能进行纹理采样了,采样的行为和设置的采样方式有关:
NEAREST
采样:返回离采样坐标最近纹素的颜色值;LINEAR
采样:返回当前纹素和其周围一定距离纹素的颜色插值结果;
需要注意的是,由于蓝色通道值被用于计算采样格子序号,导致它总是整数,会使得结果有突兀。因此可以通过读取相邻的两个格子然后插值解决: \[ \nonumber cell_{low}=\left \lfloor{B \times (N - 1)} \right \rfloor \\ cell_{high} = \left \lceil{B \times (N - 1)} \right \rceil \] 插值的算法如下: \[ \nonumber color = color_{low} \times (1 - C_{frac}) + color_{high} \times C_{frac} \] 其中\(C_{frag}\)是原蓝色通道值的小数部分。
实践
GLSL (GAMES104)
直接从GAMES104的作业2里搬过来了:
#version 310 es
#extension GL_GOOGLE_include_directive : enable
#include "constants.h"
#define ColorGridingIntensity 1.0
layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInput in_color;
layout(set = 0, binding = 1) uniform sampler2D color_grading_lut_texture_sampler;
layout(location = 0) out highp vec4 out_color;
void main()
{
// 获取LUT大小以计算格子数
highp ivec2 lut_tex_size = textureSize(color_grading_lut_texture_sampler, 0);
highp float _COLORS = float(lut_tex_size.x / lut_tex_size.y);
// 上一阶段传过来的画面
highp vec4 color = subpassLoad(in_color).rgba;
// 计算要采样第几个格子
highp float blueColor = color.b * (_COLORS - 1.0);
// 手动给蓝色值插值
highp vec2 uv1 = vec2((color.r+ floor(blueColor))/_COLORS,color.g);
highp vec2 uv2 = vec2((color.r+ ceil(blueColor))/_COLORS,color.g);
highp vec4 c1 = texture(color_grading_lut_texture_sampler, uv1);
highp vec4 c2 = texture(color_grading_lut_texture_sampler, uv2);
highp vec4 newColor = mix(c1, c2, fract(blueColor));
// 按调色强度系数处理最终结果
out_color = mix(color,newColor,ColorGridingIntensity);
}
效果如下:
我的OpenGL渲染器, TODO
参考资料
- Grading shader tutorial (defold.com)
- qyz3112746/Games104 at HW2 (github.com)