webgl智慧楼宇发光系列之线性采样下高斯模糊
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σ的高斯函数等于分布为σ的两个高斯函数的乘积。
高斯函数的这两个属性为我们提供了进行大量优化的空间。
基于第一个属性,我们可以将二维高斯函数分成两个一维函数。在使用片段着色器的情况下,我们可以将高斯滤镜分为水平模糊滤镜和垂直模糊滤镜,在渲染后仍可获得准确的结果。 这个时候,1024_1024大小的纹理,要实现33 _ 33 大小的高斯模糊,需要访问大概1024 _ 1024 _ 33*2≈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%的渲染效率。
总结
通过线性采样的机制,我们可以看到效率提高了近一倍。这在一些对性能要求高得场景或者移动终端是很有意义。
其实要做出一个好的发光效果,涉及到相关算法是很多了,而且细节之处都需要关注。
先看看我们已经做了得一些发光楼宇得案例吧, 以下都是再简单模型(立方体) + 贴图 + 光照 + 发光 出来得效果,如果模型层面在优化,应该还可以有更酷效果:
如果对可视化感兴趣,可以和我交流,微信541002349. 另外关注公众号“ITMan彪叔” 可以及时收到更多有价值的文章。
参考文档
参考文档:http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
本文部分素材使用了参考文档中的内容。
webgl智慧楼宇发光系列之线性采样下高斯模糊的更多相关文章
- webgl智慧楼宇发光效果算法系列之高斯模糊
webgl智慧楼宇发光效果算法系列之高斯模糊 如果使用过PS之类的图像处理软件,相信对于模糊滤镜不会陌生,图像处理软件提供了众多的模糊算法.高斯模糊是其中的一种. 在我们的智慧楼宇的项目中,要求对楼宇 ...
- 基于 HTML5 WebGL 的智慧楼宇可视化系统
前言 可视化的智慧楼宇在 21 世纪是有急迫需求的,中国被世界称为"基建狂魔",全球高层建筑数量位居首位,所以对于楼宇的监控是必不可少.智慧楼宇可视化系统更多突出的是管理方面的功能 ...
- 基于 HTML5 WebGL 的智慧楼宇三维可视化监控
前言 可视化的智慧楼宇在 21 世纪是有急迫需求的,中国被世界称为"基建狂魔",全球高层建筑数量位居首位,所以对于楼宇的监控是必不可少.智慧楼宇可视化系统更多突出的是管理方面的功能 ...
- 使用three.js(webgl)搭建智慧楼宇、设备检测、数字孪生——第十三课
老子云:有道无术,术尚可求,有术无道,止于术. 咱开篇引用老子的话术,也没其它意思,只是最近学习中忽有感悟,索性就写了上来. 这句话用现代辩证思维理解,这里的"道" 大抵是指方法论 ...
- 基于 HTML5 WebGL 的 智慧楼宇能源监控系统
前言 21世纪,在能源危机和全球气候变暖的压力下,太阳能等可再生能源越来越受到关注,其中光伏建筑一体化逐渐成为绿色发展方式和生活方式,加强节能降耗,支持低碳产业和新能源.可再生能源发展,也已经成为国家 ...
- WEBGL 2D游戏引擎研发系列 第一章 <新的开始>
WEBGL 2D游戏引擎研发系列 第一章 <新的开始> ~\(≥▽≤)/~HTML5游戏开发者社区(群号:326492427) 转载请注明出处:http://html5gamedev.or ...
- 数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解
数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解 对数组有不了解的可以先看看我的另一篇文章,那篇文章对数组有很多详细的解析,而本篇文章则着重讲动态数组,另一篇文章链接 ...
- .Neter玩转Linux系列之六:Linux下MySQL的安装、配置、使用
一.Linux安装MySQL (1)下载安装包:https://dev.mysql.com/downloads/mysql/ (2)解压并安装 命令:tar zxvf 文件名 解压完成之后,重名一下文 ...
- .Neter玩转Linux系列之三:Linux下的分区讲解
基础篇 .Neter玩转Linux系列之一:初识Linux .Neter玩转Linux系列之二:Linux下的文件目录及文件目录的权限 .Neter玩转Linux系列之三:Linux下的分区讲解 .N ...
- .Neter玩转Linux系列之四:Linux下shell介绍以及TCP、IP基础
基础篇 .Neter玩转Linux系列之一:初识Linux .Neter玩转Linux系列之二:Linux下的文件目录及文件目录的权限 .Neter玩转Linux系列之三:Linux下的分区讲解 .N ...
随机推荐
- Stable Diffusion 术语表
Stable Diffusion 术语表 说明 原文地址:https://theally.notion.site/The-Definitive-Stable-Diffusion-Glossary-1d ...
- XML Schema 字符串数据类型及约束详解
字符串数据类型用于包含字符字符串的值.字符串数据类型可以包含字符.换行符.回车符和制表符. 以下是模式中字符串声明的示例: <xs:element name="customer&quo ...
- 为WPF框架Prism注册Nlog日志服务
这篇文章介绍了为WPF框架Prism注册Nlog日志服务的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 无论是Nlog还是Serilog, 它们都提供 ...
- C#复杂类型转为QueryString
使用 visual studio 创建 webapi 项目,并添加 DefaultController.cs,代码如下 public class DefaultController : ApiCont ...
- Windows平台git clone文件路径太长报错
问题描述 在Windows下拉取一些比较大的开源项目经常会提示文件路径太长(filename too long),然后死活都不成功 解决办法 1.配置git git config --system c ...
- uniapp 页面跳转传值和接收
前端面试题库地址:https://www.yuque.com/sxd_panda/sdluga 1.首先介绍最原始的跳转方法,类似于html中的a标签,不过在uniapp中需要将a标签换成 <n ...
- 【WPF】Dispatcher 与消息循环
这一期的话题有点深奥,不过按照老周一向的作风,尽量讲一些人鬼都能懂的知识. 咱们先来整个小活开开胃,这个小活其实老周在 N 年前写过水文的,常阅读老周水文的伙伴可能还记得.通常,咱们按照正常思路构建的 ...
- minos 2.3 中断虚拟化——GICv2 管理
首发公号:Rand_cs 硬件肯定需要软件配合,这一节就来实战 GICv2 首先准备好 GICv2 手册:https://developer.arm.com/documentation/ihi0048 ...
- 使用线程池实现为多个客户端提供Echo服务
import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; im ...
- 编程语言界的丐帮 C#.NET FRAMEWORK 4.6 EF 连接MYSQL
1.nuget 引用 EntityFramework .和 MySql.Data.EntityFramework. EntityFramework 版本:6.4.4,MySql.Data.Entit ...