可视化/数字孪生专业社区
资源中心
问答
文章
实用工具
ByteVCharts
开源中台
申请建模
申请帮助
登录
注册
申请协助
此单为
付费
协助
×
为协助帮威客用户快速入门,帮威客平台可损供用户特定项目的框架代码开发服务。该服务可为用户快速构建符合项目基本需求的3D可视化框架代码资源(包括源码、3D模型、贴图、数据等),用户的技术团队可在此基础上快速上手,大幅提高3D可视化项目成功基础。
预算金额
公司名称
联系人
微信号
手机号码
提交申请
申请协助
此单为
付费
协助
×
为协助帮威客用户快速入门,帮威客平台可损供用户特定项目的框架代码开发服务。该服务可为用户快速构建符合项目基本需求的3D可视化框架代码资源(包括源码、3D模型、贴图、数据等),用户的技术团队可在此基础上快速上手,大幅提高3D可视化项目成功基础。
预算金额
公司名称
联系人
微信号
手机号码
提交申请
业务咨询
开发咨询
微信咨询
杜老师
黄老师
熊老师
支付信息
×
购买文章
用three.js炫酷的城市扫光效果
订单金额
¥
0
实付金额
¥
0
我已阅读并同意ByteV组件购买协议
取消
提交订单
支付宝支付
微信支付
提交订单
0
点赞
0
评论
收藏
分享
举报
用three.js炫酷的城市扫光效果
Terry
关注
已关注
0
0
0
2310
发表于 2020-08-20 17:50:31
最近由于工作需要实现一些比较炫酷的3d城市扫光效果,现在分享给大家思路和方法 先看效果图: ![](https://img-blog.csdnimg.cn/20200208193327226.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3poZ3UxOTky,size_16,color_FFFFFF,t_70)![在这里插入图片描述](https://img-blog.csdnimg.cn/20200208193340909.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3poZ3UxOTky,size_16,color_FFFFFF,t_70) 具体怎么实现的那? 首先像扫光这种效果是3D比较基本的效果,我们可以使用后处理、模版、材质三种方式来实现,鉴于后处理和模版这两块用three.js构建起来如果大家不熟悉会非常困难(但是维护起来确非常简单,如果实现了MRT,用后处理的方式性能也是最好的),因此本篇主要讲述如何用材质的方式来实现扫光效果。 用材质实现也有两种思路: 第一种,我们可以回忆下点光源是如何实现的,就是在片元着色器判断该点光源到每一个片元的距离,对吧?按照这种思路,我们如果实现圆环形扫光就可以直接在片元判断该片元是否在这个环形区域内就搞定了,如果是片形扫光我们可以判断该片元是否在该包围盒内对吧。 下面看下片形扫光着色器代码 vertexShader: ``` varying vec4 v_position; #include
#include
//这个是为了支持logDepth #ifdef USE_RELATIVE uniform mat4 relativeModelMatrix; #endif void main() { vec4 pos = vec4(position, 1.0); gl_Position = projectionMatrix * modelViewMatrix * pos; #include
#ifdef USE_RELATIVE v_position = relativeModelMatrix * pos; #else v_position = pos; #endif } ``` ``` `fragmentShader:` uniform vec3 color; uniform vec3 maxPos; uniform vec3 minPos; varying vec4 v_position; #ifdef USE_UVMAP uniform sampler2D uvMap; #endif uniform vec3 direction; #include
bool isMax(vec3 a, vec3 b){ float ax = a.x; float ay = a.y; float az = a.z; float bx = b.x; float by = b.y; float bz = b.z; return ax > bx && ay > by && az > bz; } bool isMin(vec3 a, vec3 b){ float ax = a.x; float ay = a.y; float az = a.z; float bx = b.x; float by = b.y; float bz = b.z; return ax < bx && ay < by && az < bz; } void main() { #include
float subb = length(maxPos.z - minPos.z); float gap = length(v_position.z - minPos.z); vec2 texCoord = vec2((gap / subb), 0.5); gl_FragColor = mix(vec4(0,0,0,0),vec4(color, 1.0),float(isMin(v_position.xyz,maxPos) && isMax(v_position.xyz,minPos))); #ifdef USE_UVMAP gl_FragColor.a *= texture2D( uvMap, texCoord ).r;//可以传入一个渐变贴图,防止扫光太生硬 #endif } ``` 看一下是不是非常简单,就是模拟一个包围盒,将该包围盒的minPos和maxPos传入,然后在片元判断每个片元的position是否在该包围盒里,也就是 gl_FragColor = mix(vec4(0,0,0,0),vec4(color, 1.0),float(isMin(v_position.xyz,maxPos) && isMax(v_position.xyz,minPos)));如果在包围盒里就渲染扫光区域,如果不在就渲染成透明的,这样就有了扫光效果。 我们分析下用这种方式实现扫光的利与弊: 好处:1.用这种方式实现你就可以随意控制包围盒,可以平着扫,可以斜着扫(斜着扫会有冲击的效果) 2.性能也不错 3.通用性强,任意的物体你都可以扫 弊端:1.用这种方式维护起来非常困难,因为在地球上实现扫光,包围盒的构建还是比较麻烦的,而且大尺度下精度不够,还需要使用相对值。 2.如果要实现圆形扫光或者任意图形扫光又要再写一个材质,用户很难自定义。 下图是该材质下的效果,还是很炫酷的,哈哈: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200208195119120.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3poZ3UxOTky,size_16,color_FFFFFF,t_70) ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200208195215446.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3poZ3UxOTky,size_16,color_FFFFFF,t_70) 下面介绍第二种方式:计算uv 这种思路非常简单,就是哪些物体需要扫光效果,我们就为它们整体计算uv,为这个区域预先计算出水平包围盒,然后整体去计算uv,如果我们不需要冲击的效果,可以让物体的高度不影响uv的权重,如果想有冲击的效果则高度应该给一个权重(注:如果实在不理解怎么计算uv,而且你又是用geojson创建的楼宇,那你可以用经纬度直接计算uv,这种方式最简单。所有uv的计算建议在worker中计算) 预处理完uv之后,我们可以想象一下,我们贴什么图,就可以扫出什么形状来,而且还可以用材质动画作出更加炫酷的效果,这些效果可以直接给美工,让他们去做,哈哈,是不是顿时轻松了许多(本人建议,效果方面能传图片的千万不要写shader,因为如果可以用图片实现,那么想要什么效果,用户可以直接去找美术,哈哈哈) 好了,看看着色器吧 vertexShader: ``` #include
#include
varying vec2 vp; uniform mat3 uvTransform; attribute vec2 coordinates; void main() { vec4 pos = vec4(position, 1.0); vec2 vUv = ( uvTransform * vec3( coordinates, 1 ) ).xy; vp = vUv; gl_Position = projectionMatrix * modelViewMatrix * pos; #include
} ``` fragmentShader: ``` varying vec2 vp; uniform vec3 scanningColor; uniform sampler2D map; #include
void main(){ #include
float r = texture2D(map, vp).r; gl_FragColor = r * vec4(scanningColor, 1.0); } ``` 是不是非常简单: 我们传入一张图片 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200208200155318.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3poZ3UxOTky,size_16,color_FFFFFF,t_70) 效果: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200208193232823.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3poZ3UxOTky,size_16,color_FFFFFF,t_70) 是不是还挺炫酷
点击查看更多
全部评论
登录
|
注册
关于作者
Terry
TA的个人主页
关注
已关注
文章
52
粉丝
31
获赞
15
评论
8
访问
81406
ThreeJS 轮廓线特效 OutLinePath
创建海洋特效组件 THREEJS 海洋效果 Shader实现
ThreeJS后期处理通道
Three.js物理材质MeshStandardMaterial和MeshPhysicalMaterial
ThreeJs光效流转特效
推荐文章
ThreeJS 轮廓线特效 OutLinePath
(3)、React中使用ECharts——柱状图
31个惊艳的数据可视化作品,让你感受“数据之美”!
防抖节流
创建海洋特效组件 THREEJS 海洋效果 Shader实现
文章目录
文章分享
×
扫一扫分享
复制链接