“熱成像”風格的效果是怎么實現(xiàn)的?(內(nèi)附源碼)

之前轉(zhuǎn)載過知乎上面的一篇文章:
作者:這是上帝的杰作
鏈接:https://zhuanlan.zhihu.com/p/344110917

文章詳細講解了 Shader 實現(xiàn)“熱成像”效果的思路,但是并沒有給出完整的實現(xiàn)代碼,后臺有讀者多次催促,希望我能實現(xiàn)下并給出完整的代碼,于是,今天晚上就花了一點時間簡單實現(xiàn)了下這個效果。
按照那篇文章的思路,主要步驟是:模糊->發(fā)光->亮度分級->替換顏色 ,其中發(fā)光這一步不大重要。
可以觀察到“熱成像”效果的顏色也就是藍色(冷)和紅色(熱)組合的幾種顏色,然后對顏色做一個排序,并根據(jù)亮度等級替換對應(yīng)的顏色。
至于做模糊,其實就是為了增加層次感而已,可以對比下面的兩幅圖,左邊的是沒有做模糊的“熱成像效果”。

根據(jù)“熱成像”的色譜創(chuàng)建一個顏色查找數(shù)組:
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 轉(zhuǎn)換為灰度值,我們將灰度值分為 9 個 level ,然后根據(jù)當前灰度值,選擇相應(yīng)的顏色。
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);
最終的效果如下:

完整實現(xiàn)代碼:
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;//發(fā)光
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 --
進技術(shù)交流群,掃碼添加我的微信:Byte-Flow
獲取相關(guān)資料和源碼
推薦:
全網(wǎng)最全的 Android 音視頻和 OpenGL ES 干貨,都在這了
面試官:如何利用 Shader 實現(xiàn) RGBA 到 NV21 圖像格式轉(zhuǎn)換?
項目疑難問題解答、大廠內(nèi)部推薦、面試指導(dǎo)、簡歷指導(dǎo)、代碼指導(dǎo)、offer 選擇建議、學習路線規(guī)劃,可以點擊找我一對一解答。
