“热成像”风格的效果是怎么实现的?(内附源码)
之前转载过知乎上面的一篇文章:
作者:这是上帝的杰作
链接:https://zhuanlan.zhihu.com/p/344110917
文章详细讲解了 Shader 实现“热成像”效果的思路,但是并没有给出完整的实现代码,后台有读者多次催促,希望我能实现下并给出完整的代码,于是,今天晚上就花了一点时间简单实现了下这个效果。
按照那篇文章的思路,主要步骤是:模糊->发光->亮度分级->替换颜色 ,其中发光这一步不大重要。
可以观察到“热成像”效果的颜色也就是蓝色(冷)和红色(热)组合的几种颜色,然后对颜色做一个排序,并根据亮度等级替换对应的颜色。
至于做模糊,其实就是为了增加层次感而已,可以对比下面的两幅图,左边的是没有做模糊的“热成像效果”。
根据“热成像”的色谱创建一个颜色查找数组:
vec3 colorLevels[9] = vec3[9](
vec3(234.0,51.0,61.0),
vec3(235.0,70.0,105.0),
vec3(178.0,119.0,37.0),
vec3(247.0,206.0,70.0),
vec3(149.0,232.0,71.0),
vec3(103.0,200.0,250.0),
vec3(68.0,132.0,245.0),
vec3(40.0,3.0,143.0),
vec3(18.0,5.0,62.0)
);
接下来将 rgb 转换为灰度值,我们将灰度值分为 9 个 level ,然后根据当前灰度值,选择相应的颜色。
float lum = dot(color.rgb, vec3(0.3, 0.59, 0.11));
lum = 1.0 - lum;
float d = 1.0 / 9.0;//将灰度值分为 9 个 level
int i = int(lum / d);
i = clamp(i, 0, 8);
fragColor = vec4(colorLevels[i]/255.0, 1.0);
最终的效果如下:
完整实现代码:
vec3 colorLevels[9] = vec3[9](
vec3(234.0,51.0,61.0),
vec3(235.0,70.0,105.0),
vec3(178.0,119.0,37.0),
vec3(247.0,206.0,70.0),
vec3(149.0,232.0,71.0),
vec3(103.0,200.0,250.0),
vec3(68.0,132.0,245.0),
vec3(40.0,3.0,143.0),
vec3(18.0,5.0,62.0)
);
float blur_gauss(float bhqp, float x) {
return exp (-(x * x) / (2.0 * bhqp * bhqp));
}
vec4 blur(vec2 uv, sampler2D source, float Intensity) {
const int iterations = 4;
int halfIterations = iterations / 2;
float sigmaX = 0.1 + Intensity * 0.5;
float sigmaY = sigmaX;
float total = 0.0;
vec4 ret = vec4 (0., 0., 0., 0.);
float step = 0.00390625;
for (int iy = 0; iy < iterations; ++iy) {
float fy = blur_gauss(sigmaY, float (iy - halfIterations));
float offsety = float (iy - halfIterations) * step;
for (int ix = 0; ix < iterations; ++ix) {
float fx = blur_gauss(sigmaX, float (ix - halfIterations));
float offsetx = float (ix - halfIterations) * step;
total += fx * fy;
vec4 a = texture2D (source, uv + vec2 (offsetx, offsety));
a.rgb *= a.a;
ret += a * fx * fy;
}
}
return ret / total;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / iResolution.xy;
//vec4 color = texture2D(iChannel0, uv);
vec4 color = blur(uv, iChannel0, 3.0);//模糊
color.rgb += vec3(1.0,0.0,0.5)*color.rgb*0.2;//发光
float lum = dot(color.rgb, vec3(0.3, 0.59, 0.11));
lum = 1.0 - lum;
float d = 1.0 / 9.0;
int i = int(lum / d);
i = clamp(i, 0, 8);
fragColor = vec4(colorLevels[i]/255.0, 1.0);
}
参考文章:
https://zhuanlan.zhihu.com/p/344110917
-- END --
进技术交流群,扫码添加我的微信:Byte-Flow
获取相关资料和源码
推荐:
全网最全的 Android 音视频和 OpenGL ES 干货,都在这了
面试官:如何利用 Shader 实现 RGBA 到 NV21 图像格式转换?
项目疑难问题解答、大厂内部推荐、面试指导、简历指导、代码指导、offer 选择建议、学习路线规划,可以点击找我一对一解答。
评论