前言
1.在Piccolo小引擎代码中找到Piccolo/engine/shader/glsl/color_grading.frag,补充此shader代码中的main函数,以实现ColorGrading功能。若代码编译成功且实现方法正确,则可以看到进行ColorGrading渲染之后的结果
2.使用自定义的LUT图,并修改相应代码,实现具有个性的ColorGrading的效果
一、实现一个渲染功能
在此之前,我们可以先看一丢丢基础知识
用户LUT是一种简单的颜色分级方法:将屏幕上的像素替换为您提供的LUT中的新值,本质上只是一个原颜色到新颜色的映射,效果类似与滤镜
思路是以原颜色的RGB值为坐标,采样一张纹理,得到新颜色,这张纹理叫做LUT(Lookup Table),LUT的示例如下:
LUT可视作一组方形纹理的横向拼凑,其保存颜色数据的结构可以这样理解:
可以看出上面这个长条状图形的每一个小正方形的B值是不变的,放大后为上图下半部分所示
R:每个方形纹理内,R值在水平往右的方向上由0-1递增
G:每个方形纹理内,G值在竖直往下的方向上由0-1递增
B:每个方形纹理内,B值不变;B值对于横向拼凑的一组方形纹理而言,从左往右由0-1递增,如上图的上半部分一样,蓝色逐渐加深
也可以将一组方形纹理想象成在空间中竖直叠加起来(可以看本文章第一张图),那么原RGB值可以作为三维坐标,映射到LUT中保存的颜色数据上,这样一张LUT图便代表一套颜色的对应关系
需要注意的是,由于原颜色RGB值为连续的,在对LUT采样时,不会完美的映射到单一纹素上,需要采样相邻的纹素并做线性插值,特别对于B值而言,需要在两个方形纹理内采样(这就是下面代码最后三行的意义,采样两次,再做线性混合)
代码都有详细的注释 对可能会用到的函数有如下总结:
若不对代码做任何改变,将输入颜色直接作为输出颜色,效果图如下:
#version 310 es
#extension GL_GOOGLE_include_directive : enable
#include "constants.h"
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()
{
highp ivec2 lut_tex_size = textureSize(color_grading_lut_texture_sampler, 0);
highp float _COLORS = float(lut_tex_size.y);
highp vec4 color = subpassLoad(in_color).rgba;
// texture(color_grading_lut_texture_sampler, uv)
out_color = color;
}
亲自实现一个渲染功能,做出一些改变:
#version 310 es
#extension GL_GOOGLE_include_directive : enable
#include "constants.h"
//像素的原颜色 in_color
layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInput in_color;
//2D贴图采样器 lut
layout(set = 0, binding = 1) uniform sampler2D color_grading_lut_texture_sampler;
//最终输出的颜色
layout(location = 0) out highp vec4 out_color;
void main()
{
//获得2D贴图的大小 是一个二维向量
highp ivec2 lut_tex_size = textureSize(color_grading_lut_texture_sampler, 0);
//将y值作为一个常数
highp float _COLORS = float(lut_tex_size.y);
//获取in_color的值
highp vec4 color = subpassLoad(in_color).rgba;
// texture(color_grading_lut_texture_sampler, uv)
//out_color = color;
//color.b 乘以 高度
//将输入颜色的蓝色通道值乘以一个常数 _COLORS,得到一个新的浮点数 b
highp float b = color.b * _COLORS;
//将浮点数 b 向下取整,得到一个新的浮点数 b_floor 用于后续采样
highp float b_floor = floor(b);
//将浮点数 b 向上取整,得到一个新的浮点数 b_ceil 用于后续采样
highp float b_ceil = ceil(b);
//从颜色分级查找表纹理中获取相应的颜色
//需要在两个方形内进行采样
highp vec4 color_floor = texture(color_grading_lut_texture_sampler, vec2((b_floor + color.r) / _COLORS, color.g));
highp vec4 color_ceil = texture(color_grading_lut_texture_sampler, vec2((b_ceil + color.r) / _COLORS, color.g));
//进行线性插值
//out_color = mix(color_floor, color_ceil, b - b_floor);
out_color = mix(color_floor, color_ceil, b_ceil - b);
}
是不是立马就有了提升画面表现的感觉!
二、自定义的LUT
小引擎预先提供了7张LUT图(在engine/asset/texture/lut下查看),我们可以先试一下效果!只需要修改engine/asset/global/rendering.global.json中的资源路径,如:
我们随便选一张,修改为上述的jpg图片,效果为:
是不是有点缤纷且傍晚的感觉!
下来我们可以试一试自定义的LUT图,这里我以my_lut为例
效果如下:
是不是有了夜景的感觉!至此,我们的目的就达到啦