“热成像”风格的效果是怎么实现的?(内附源码)

字节流动

共 5957字,需浏览 12分钟

 · 2023-10-12

之前转载过知乎上面的一篇文章:

作者:这是上帝的杰作
链接: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.30.590.11));
    lum = 1.0 - lum;
    float d = 1.0 / 9.0;//将灰度值分为 9 个 level
    int i = int(lum / d);
    i = clamp(i, 08);

    fragColor = vec4(colorLevels[i]/255.01.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.30.590.11));
    lum = 1.0 - lum;
    float d = 1.0 / 9.0;
    int i = int(lum / d);
    i = clamp(i, 08);

    fragColor = vec4(colorLevels[i]/255.01.0);
}


参考文章:

https://zhuanlan.zhihu.com/p/344110917

-- END --


进技术交流群,扫码添加我的微信:Byte-Flow



获取相关资料和源码


推荐:

Android FFmpeg 实现带滤镜的微信小视频录制功能

全网最全的 Android 音视频和 OpenGL ES 干货,都在这了

一文掌握 YUV 图像的基本处理

抖音传送带特效是怎么实现的?

所有你想要的图片转场效果,都在这了

面试官:如何利用 Shader 实现 RGBA 到 NV21 图像格式转换?

我用 OpenGL ES 给小姐姐做了几个抖音滤镜


项目疑难问题解答、大厂内部推荐、面试指导、简历指导、代码指导、offer 选择建议、学习路线规划,可以点击找我一对一解答。

浏览 621
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报