webgl智慧楼宇发光系列之线性采样下高斯模糊

前面一篇文章 <webgl智慧楼宇发光效果算法系列之高斯模糊>, 我们知道了 高斯模糊的本质原理,就是对每个像素,按照正态分布的权重去获取周边像素的值进行平均,是一种卷积操作。

同时我们可以指定周边像素的数量,比如可以是3X3,或者5X5,通用的表达就是N X N, 数字N通常称之为模糊半径,这在之前的文章的代码中有体现(uRadius):

uniform float uRadius;
float gaussianPdf(in float x, in float sigma) {
  return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;
}
void main() {
  for( int i = 1; i < MAX_KERNEL_RADIUS; i ++ ) {
    float x = float(i);
    if(x > radius){
      break;
    }
    ...
  }
  vec4 result = vec4(1.0) - exp(-diffuseSum/weightSum * uExposure);
  gl_FragColor = result;
}
`

效率问题

通常,我们希望模糊的效果越强烈,模糊半径就会要求越大。所谓的半径就是上面的数字N。
我们知道,要实现一个NxN大小的高斯模糊,在纹理的每个像素点,都需要去获取周边N个像素点。因为1024*1024大小的纹理,要实现33 * 33 大小的高斯模糊,需要访问大概1024 * 1024 * 33 * 33≈11.4亿个纹理像素,才能应用整个图像的模糊效果。

为了获得更有效的算法,我们来看看高斯函数的一些特性:

  • 二维高斯函数可以通过将两个一维高斯函数相加来计算。
  • 分布为2σ的高斯函数等于分布为σ的两个高斯函数的乘积。

高斯函数的这两个属性为我们提供了进行大量优化的空间。

基于第一个属性,我们可以将二维高斯函数分成两个一维函数。在使用片段着色器的情况下,我们可以将高斯滤镜分为水平模糊滤镜和垂直模糊滤镜,在渲染后仍可获得准确的结果。 这个时候,10241024大小的纹理,要实现33 * 33 大小的高斯模糊,需要访问大概1024 * 1024 * 332≈6,900万个纹理提取。这种优化明细减少了一个量级。文章 《webgl智慧楼宇发光效果算法系列之高斯模糊》已经实现了这一优化。

第二个属性可用于绕过平台上的硬件限制,这些平台仅在一次pass中仅支持有限数量的纹理提取。

线性采样

到此,我们知道了把一个二维的高斯模糊 分离成两个一维的高斯模糊。效率上也有了大幅度的提高。但是实际上,我们还可以通过线性采样的特性进一步提高效率。

我们知道,要获取一个像素信息,就要做一次贴图的读取。这就意味33个像素信息,就需要做33次贴图的读取操作。 但是由于在GPU上面可以随意进行双线线性插值,而没有额外的性能消耗。 这就意味着,如果我们不再像素的中心点读取贴图,就可以获得多个像素的信息。 如下图所示:


示意图

假设两个像素,我们在像素1中心点读取贴图就是获取像素1的颜色,在像素2中心点读取贴图就是获取像素2的颜色;而在像素1中心点和像素2中心点的某个位置读取贴图,则会获取像素1和像素2的颜色的加权平均的效果。

因为我们做高斯模糊的时候,本身就是获取周边相邻元素的加权平均值,因此利用线性采样的这个特性,可以把原本2个像素的采样,减少为一次采样。 如果原本33次采样,则可以减少到17次。

对于两个纹素的采样,需要调整坐标使其与纹素#1中心的距离等于纹素#2的权重除以两个权重之和。同样的,坐标与纹素#2中心的距离应该等于纹素#1的权重除以两个权重之和。

然后我们就有了计算线性采样高斯滤波的权重和位移公式:

公式

代码讲解

  • 首先定义一个uniform变量,该变量表示是否启用线性采样的方法:
uniform bool uUseLinear;
  • 然后如果使用线性采样,就把原本的采样次数减少一半:
 if(uUseLinear){
    radius = uRadius / 2.0;
  }
  • 再然后,如果使用线性采样,就使用上述的公式进行像素提取:
if(uUseLinear){
      // http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
      float t1 = 2.0 * x - 1.0,t2 = 2.0 * x ;
      float w1 = gaussianPdf(t1,fSigma);
      float w2 = gaussianPdf(t2,fSigma);
      w = w1 + w2;
      t = (t1 * w1 + t2 * w2) / w;
    }

    vec2 uvOffset = uDirection * invSize * t;
    vec4 sample1 = texture2D( uColorTexture, vUv + uvOffset).rgba;
    vec4 sample2 = texture2D( uColorTexture, vUv - uvOffset).rgba;
    diffuseSum += (sample1 + sample2) * w;
    weightSum += 2.0 * w;

最终的绘制效果如下:


效果

其中左边的未使用线性采样的机制,而右边的使用了线性采样,可以看出右边再减少了一半的采样的情况下,效果和左边的基本没有差别。

而效率上,通过测试,右边比左边大概提高了40%的渲染效率。

总结

通过线性采样的机制,我们可以看到效率提高了近一倍。这在一些对性能要求高得场景或者移动终端是很有意义。

其实要做出一个好的发光效果,涉及到相关算法是很多了,而且细节之处都需要关注。

先看看我们已经做了得一些发光楼宇得案例吧, 以下都是再简单模型(立方体) + 贴图 + 光照 + 发光 出来得效果,如果模型层面在优化,应该还可以有更酷效果:


案例0
案例1
案例2

如果对可视化感兴趣,可以和我交流,微信541002349. 另外关注公众号“ITMan彪叔” 可以及时收到更多有价值的文章。

参考文档

参考文档:http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
本文部分素材使用了参考文档中的内容。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容