threejs太阳光与阴影效果实例代码


Posted in Javascript onApril 05, 2022

前言

这篇文章实现智慧城市中模拟太阳光随时间变化产生对应场景效果。为了场景能够更逼真,我们一般会通过对接天气以及阳光等各种环境因素同步到场景中,使得场景能够更贴近现实。比如一些常见的天气系统,下雨、下雪、阴天、雾霾等,我之后会独立一篇文章中提现。这边文章主要介绍一系列灯光,主要是平行光对于太阳的模仿,以及一些材质的问题~

灯光与材质基础篇

常见的灯光:

       - 点光源 (点光源可以理解为一个同时向四面八方散发光线,我们通常用来模拟灯泡,可以产生阴影)

       - 平行光 (平行光可以想象成一个从无限远照射来的光束,通常用来模拟太阳光,可以产生阴影)

       - 聚光灯 (聚光灯字面意思就是类似舞台灯光一样,照射突出特定圆弧形范围,可以产生阴影)

       - 环境光 (一般用于改变整体场景的亮度,也是最常用的光源之一)

这里提一嘴材质:(仅仅列举常用的)

       - 网格基础材质(MeshBasicMaterial,不支持阴影)

       - FBR材质

           - 物理标准材质(MeshStandardMaterial)

           - MeshPhysicalMaterial

           - 以上两者FBR材质相对于高光网格材质效果更好

       - MeshPhongMaterial(高光网格材质,高亮表面、镜面反射)

       - MeshLambertMaterial(网格Lambert材质,暗淡,漫反射)

这里简单做一下介绍,不懂的同学可以具体去了解某个材质

太阳光

添加平行光-----从东至西调整位置-----调整亮度以及颜色-----添加过渡模拟太阳光

接下来介绍本文的重点,如何模拟太阳光照的变化。其实原理非常简单,就是添加平行光,调整场景模型的阴影关系,根据时间实时变化平行光的位置以及光照强度以及颜色即可模拟~

整体调用代码

由于是一个demo,所以注重效果,一切从简实现功能

sun() { //两秒变化一次平行光
  let i=0
  setInterval(()=>{
    this.initSun(i)
    i++
  },2000)
}

简单实现通过定时器以及提前写好对应位置光照的信息。主要是思想,酌情根据自己的需求可以改变~

这里这么写主要是实现效果,真实的应该根据系统时间将太阳光做出调整,包括根据天气原因,换汤不换药,主要还是

手动调整并存储为json通过传入时间以及天气去做出转化~ 

Viewer.prototype.initSun = function (type) {
  let position = {}
  let color = '#ffffff'
  let intensity = 1
  switch (type) {
    case 0:
      position = {
        x: 270,
        y: 150,
        z: 0
      }
      intensity = 5
      break
    case 1:
      position = {
        x: 258,
        y: 170,
        z: 0
      }
      intensity = 7
      color = '#fcffc9'
      break
    case 2:
      position = {
        x: 245,
        y: 180,
        z: 0
      }
      intensity = 10
      color = '#ffe69f'
      break
    case 3:
      position = {
        x: 0,
        y: 100,
        z: 0
      }
      intensity = 15
      color = '#ffe69f'
      break
    case 4:
      position = {
        x: -245,
        y: 180,
        z: 0
      }
      intensity = 10
      color = '#e3894d'
      break
    case 5:
      position = {
        x: -258,
        y: 160,
        z: 0
      }
      intensity = 10
      color = '#ff8400'
      break
    default :
      position = {
        x: -270,
        y: 150,
        z: 0
      }
      intensity = 8
      color = '#ff8400'
      break
  }
  if (this.directionalLight) {
    this.directionalLight.setSun(position,color,intensity)
  } else {
    this.directionalLight = new zhdSun()
    this.directionalLight.renderFn(this.renderFunction)
    this.directionalLight.init({
      position,
      color,
      intensity,
      scene: this.scene,
      currentlayers: this.currentlayers
    })
  }
}

太阳光类

这里主要对太阳光类的拆解与分析,封装的比较粗糙,酌情个人可以优化

import TWEEN from '@tweenjs/tween.js'
import {zhdObject} from './zhdObject'
export class zhdSun extends zhdObject {
  constructor() {
    super()
    this.light = null
  }
}
//由于添加了TWEEN动画库,记得在animate中实时更新TWEEN
TWEEN.update()

初始化

这里做的是向场景中添加平行光,设置其阴影的范围以及距离等属性,因为我这边涉及层级,所以设置了平行光的层级

平行光可谓是所有灯光中阴影调整最麻烦的,想要平行光能够产生对的阴影效果,模型的产生阴影以及接收阴影要调整好,并且平行光的照射范围也要调整好。我效果图中不知大家有没有发现,在正午时刻的时候太阳光照射地面产生了一个长方形的范围阴影,这里是特地录制一个相对不那么完美的版本。

产生原因:平行光范围太小,但是一旦你调整平行光范围过大,由于地面是通过多个瓦片加载的,就会出现条纹状的阴影

如下图

解决方法:调整平行光阴影的bias属性,有助于减少阴影中的伪影

threejs太阳光与阴影效果实例代码

init({position, color, intensity , currentlayers, scene}) {
  const directionalLight = new THREE.DirectionalLight(color, intensity) // 新建一个平行光源,颜色未白色,强度为1
  this.light = directionalLight
  directionalLight.position.set(position.x, position.y, position.z) // 将此平行光源调整到一个合适的位置
  directionalLight.castShadow = true // 将此平行光源产生阴影的属性打开
  // 设置平行光的的阴影属性,即一个长方体的长宽高,在设定值的范围内的物体才会产生阴影
  const d =100 //阴影范围
  directionalLight.shadow.camera.left = -d
  directionalLight.shadow.camera.right = d
  directionalLight.shadow.camera.top = d
  directionalLight.shadow.camera.bottom = -d
  directionalLight.shadow.camera.near = 20
  directionalLight.shadow.camera.far = 8000
  directionalLight.shadow.mapSize.x = 2048 // 定义阴影贴图的宽度和高度,必须为2的整数此幂
  directionalLight.shadow.mapSize.y = 2048 // 较高的值会以计算时间为代价提供更好的阴影质量
  directionalLight.shadow.bias = -0.0005 //解决条纹阴影的出现
  this.setlayers(directionalLight, currentlayers)
  scene.add(directionalLight) // 将此平行光源加入场景中,我们才可以看到这个光源
  return directionalLight
}

设置平行光信息

设置平行光的信息:包括位置、颜色、强度

setSun(position, color, intensity) {
  this.setTweens(this.light.position, position, 2000)
  this.light.color = new THREE.Color( color )
  this.light.intensity = intensity
}

Tween

这里简单介绍TWEEN不懂的可以去看我之前的文章,主要是一个动画库,这里做简单的封装

setTweens(obj, newObj, duration = 1500) {
  var ro = new TWEEN.Tween(obj)
  ro.to(newObj, duration) // 变化后的位置以及动画时间
  ro.easing(TWEEN.Easing.Sinusoidal.InOut)
  ro.onUpdate(function () {
  })
  ro.start()
}

总结

到此这篇关于threejs太阳光与阴影效果的文章就介绍到这了,更多相关threejs太阳光与阴影内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
原创javascript小游戏实现代码
Aug 19 Javascript
动态加载js和css(外部文件)
Apr 17 Javascript
使用jQuery插件创建常规模态窗口登陆效果
Aug 23 Javascript
深入理解Java线程编程中的阻塞队列容器
Dec 07 Javascript
js获取鼠标位置实例详解
Dec 09 Javascript
JavaScript中eval函数的问题
Jan 31 Javascript
javascript函数自动执行常用方法汇总
Mar 28 Javascript
jQuery tagsinput在h5邮件客户端中应用详解
Sep 26 Javascript
vue cli 3.0 搭建项目的图文教程
May 17 Javascript
JS/CSS实现字符串单词首字母大写功能
Sep 03 Javascript
Vue组件化开发之通用型弹出框的实现
Feb 28 Javascript
react 不用插件实现数字滚动的效果示例
Apr 14 Javascript
JS实现数组去重的11种方法总结
Apr 04 #Javascript
vue使用wavesurfer.js解决音频可视化播放问题
Apr 04 #Vue.js
JavaScript模拟实现网易云轮播效果
Javascript中Microtask和Macrotask鲜为人知的知识点
vue中div禁止点击事件的实现
Apr 02 #Vue.js
Vue组件更新数据v-model不生效的解决
Apr 02 #Vue.js
Vue+TypeScript中处理computed方式
Apr 02 #Vue.js
You might like
收音机史话 - 1960年代前后的DIY
2021/03/02 无线电
PHP遍历某个目录下的所有文件和子文件夹的实现代码
2013/06/28 PHP
PHP+MySql+jQuery实现的"顶"和"踩"投票功能
2016/05/21 PHP
非常好的js代码
2006/06/27 Javascript
Prototype使用指南之form.js
2007/01/10 Javascript
jquery的live使用注意事项
2014/02/18 Javascript
JavaScript实现列表分页功能特效
2015/05/15 Javascript
JS实现的文字与图片定时切换效果代码
2015/10/06 Javascript
Node.js 数据加密传输浅析
2016/11/16 Javascript
jQuery模拟淘宝购物车功能
2017/02/27 Javascript
JS中关于正则的巧妙操作
2017/08/31 Javascript
详解如何使用webpack打包JS
2018/06/21 Javascript
Node.js 实现远程桌面监控的方法步骤
2019/07/02 Javascript
解决微信小程序scroll-view组件无横向滚动的问题
2020/02/04 Javascript
[01:08:24]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第一场 2月5日
2021/03/11 DOTA
自动化Nginx服务器的反向代理的配置方法
2015/06/28 Python
Python selenium 三种等待方式解读
2016/09/15 Python
python中如何使用朴素贝叶斯算法
2017/04/06 Python
使用matplotlib画散点图的方法
2018/05/25 Python
对Python中内置异常层次结构详解
2018/10/18 Python
Python连接Oracle之环境配置、实例代码及报错解决方法详解
2020/02/11 Python
python GUI库图形界面开发之PyQt5状态栏控件QStatusBar详细使用方法实例
2020/02/28 Python
jupyter修改文件名方式(TensorFlow)
2020/04/21 Python
Python自定义sorted排序实现方法详解
2020/09/18 Python
Python通过yagmail实现发送邮件代码解析
2020/10/27 Python
HTML5 3D旋转相册的实现示例
2019/12/03 HTML / CSS
WiFi云数码相框:Nixplay
2018/07/05 全球购物
意大利奢侈品多品牌集合店:TheDoubleF
2019/08/24 全球购物
代理协议书范本
2014/04/22 职场文书
个人求职自荐信范文
2014/06/20 职场文书
三八活动策划方案
2014/08/17 职场文书
教师群众路线心得体会
2014/11/04 职场文书
儿园租房协议书范本
2014/12/02 职场文书
民事调解书范文
2015/05/20 职场文书
巴黎圣母院读书笔记
2015/06/26 职场文书
Python爬取科目四考试题库的方法实现
2021/03/30 Python