【Threejs基础教程-光影篇】5.2 Threejs 阴影系统

5.2 Threejs阴影系统

  • 学习ThreeJS的捷径
  • 在用光影系统之前
    • threejs是实时光影
    • web端目前没有优质的实时光影
    • 实时光影会大幅增加渲染压力
    • 没有独显的电脑不建议添加实时光影
  • 阴影配置
    • 什么样的灯光可以产生阴影
    • 什么样的物体可以产生阴影和接受阴影
    • 注意开启阴影渲染
    • 灵活运用阴影
  • 平行光阴影
  • 点光源阴影
  • 聚光灯阴影
  • 优化阴影
    • 阴影范围外一片漆黑,可以优化一下吗
    • 增加阴影的精度
    • 消除伪影
  • 静态阴影渲染 / 渐进式阴影渲染
  • 烘培阴影
  • 使用阴影时需要注意的点
  • Threejs基础教程在此完结,后续请查阅本人的: Threejs进阶教程

学习ThreeJS的捷径

本段内容会写在0篇以外所有的,本人所编写的Threejs教程中

对,学习ThreeJS有捷径
当你有哪个函数不懂的时候,第一时间去翻一翻文档
当你有哪个效果不会做的时候,第一时间去翻一翻所有的案例,也许就能找到你想要的效果
最重要的一点,就是,绝对不要怕问问题,越怕找找别人问题,你的问题就会被拖的越久

如果你确定要走WebGL/ThreeJS的开发者路线的话,以下行为可以让你更快的学习ThreeJS

  1. 没事就把所有的文档翻一遍,哪怕看不懂,也要留个印象,至少要知道Threejs有什么
  2. 没事多看看案例效果,当你记忆的案例效果足够多时,下次再遇到相似问题时,你就有可能第一时间来找对应的案例,能更快解决你自己的问题
  3. 上述案例不只是官网的案例,郭隆邦技术博客,跃焱邵隼,暮志未晚等站点均有不少优质案例,记得一并收藏
    http://www.yanhuangxueyuan.com/ 郭隆邦技术博客
    https://www.wellyyss.cn/ 跃焱邵隼
    http://www.wjceo.com/ 暮志未晚 (暮老的站点最近挂了,如果有人发现了最新的地址请告知博主)
    这三个站点是我最常逛的站点,推荐各位有事没事逛一下,看看他们的案例和写法思路,绝对没坏处

在用光影系统之前

threejs是实时光影

实时光影是指:光影会随着灯光的改变而改变,且变化速率非常高,参与渲染过程,

web端目前没有优质的实时光影

实时光影一般在B端不会有太好的效果,只有在C端环境下,且需要更强力的硬件支持,才能达到更好的实时光影渲染效果,像实时光追系统,就是C端专属的功能,且对显卡消耗也是巨大,也许未来某一天,随着WebGPU发展的更多,对显卡的使用更加完美后,实时光影或许也会登陆B端,这里我们可以暂且期待一下

实时光影会大幅增加渲染压力

物体越多,光影渲染增加的渲染压力就越高,对大多数情况下,渲染压力会增加一倍,如果你的设备,本身能承担的面数,大概是1000万,那么你用了实时光影后,大概这个极限会缩减到500万甚至更低,所以谨慎使用实时光影

元素越多,点线面越多,都会对最终实时光影的渲染计算量有影响

没有独显的电脑不建议添加实时光影

没有独显的电脑,本身渲染压力已经非常大了,再添加光影,cpu只会压力更大

笔记本一定要看清楚,你的浏览器是否使用独显渲染,别让CPU干渲染的活

阴影配置

什么样的灯光可以产生阴影

在目前threejs的系统下,一共有三个灯光可以产生阴影,分别是

PointLight 点光源
DirectionalLight 平行光
SpotLight 聚光灯

什么样的物体可以产生阴影和接受阴影

不是所有的物体都可以产生阴影和接受阴影

灯光只能产生阴影,不能接收阴影

可以产生并接受阴影的物体有:Mesh,Line等

不能直接产生阴影且不能接收阴影的有:Object3D,Group,

完全不产生阴影且不能接收阴影的有:Sprite(精灵),Points(粒子系统)

注意开启阴影渲染

阴影渲染是有开关的,在renderer下
在这里插入图片描述
当允许渲染阴影的时候,Threejs才会开启阴影渲染系统,否则你怎么让物体产生接收阴影,你都看不到任何的光影效果

	//开启阴影渲染renderer.shadowMap.enabled = true;

阴影可以做一些设置,比如说,允许自动更新光影,以及定义阴影类型,一般我们要使得实时光影效果最好,建议使用
THREE.PCFSoftShadowMap,如果你觉得性能太差,使用PCFShadowMap或者更低的BasicShadowMap

关于VSM阴影,这里挖个坑,后续有机会详细讲解,如果你在用PCFSoft的时候,调整不出来正确的光影效果,可以尝试使用VSM阴影来解决

灵活运用阴影

上面提到了,阴影系统可以设置产生阴影和接收阴影,所以你也可以指定某个物体仅接收阴影,但是不产生阴影,也可以设置某个物体只产生阴影不接收阴影,来实现某些效果
也可以通过设置渲染器是否自动更新阴影,来让阴影的渲染变成单帧渲染

平行光阴影

在这里插入图片描述
这里官方描述的并不是很清楚,我们写一段代码来研究这个阴影

首先,我们要先让阴影系统生效

    import * as THREE from "../three/build/three.module.js";import {OrbitControls} from "../three/examples/jsm/controls/OrbitControls.js";window.addEventListener('load',e=>{init();addLight();//添加灯光addLand();//添加地面addMesh();//添加物体render();})let scene,renderer,camera;let orbit;let mesh;function init(){scene = new THREE.Scene();renderer = new THREE.WebGLRenderer({alpha:true,antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);//渲染器开启阴影,并使用PCF算法过滤阴影,且使用软阴影renderer.shadowMap.enabled = true;renderer.shadowMap.type = THREE.PCFSoftShadowMap;document.body.appendChild(renderer.domElement);camera = new THREE.PerspectiveCamera(50,window.innerWidth/window.innerHeight,0.1,2000);camera.position.set(10,10,10);orbit = new OrbitControls(camera,renderer.domElement);orbit.enableDamping = true;}function addLight() {//添加平行光let directionalLight = new THREE.DirectionalLight(0xffffff,1.0);//设置平行光产生阴影directionalLight.castShadow = true;//设置平行光位置directionalLight.position.set(0,20,20);//平行光辅助线let directionalLightHelper = new THREE.DirectionalLightHelper(directionalLight,1,0xff0000);//平行光光影辅助线let cameraHelper = new THREE.CameraHelper(directionalLight.shadow.camera);//将物体添加到场景中scene.add(directionalLight);scene.add(directionalLightHelper);scene.add(cameraHelper);}function addMesh() {let geometry = new THREE.TorusKnotGeometry(5,1,64,8);let material = new THREE.MeshBasicMaterial({color:0xffffff * Math.random()});mesh = new THREE.Mesh(geometry,material);//给物体添加生成阴影和接收阴影的设置mesh.castShadow = true;mesh.receiveShadow = true;mesh.position.y = 3;scene.add(mesh);}function addLand() {//添加一个地面let geometry = new THREE.PlaneGeometry(100,100).rotateX(-Math.PI/2);let material = new THREE.MeshStandardMaterial({color:0xffffff});let mesh = new THREE.Mesh(geometry,material);//设定地面仅接收阴影  因为我们使用的是个地面,所以没必要再让它生成阴影浪费算力,除非你的地下有东西mesh.receiveShadow = true;scene.add(mesh);}function render() {renderer.render(scene,camera);orbit.update();requestAnimationFrame(render);mesh.rotation.x += 0.01;mesh.rotation.y += 0.01;}

在这里插入图片描述
从效果中,我们可以清晰的看到,阴影是有范围的,这个范围就是cameraHelper的范围
这是因为,阴影的计算,是借助了相机的算法来计算的,平行光内部使用了正交相机OrthographicCamera来计算阴影

我们可以打印平行光,来看到阴影的基本数据,也可以通过添加CameraHelper来查看实际计算的阴影范围

在这里插入图片描述
现在我们上面的效果,遇到了明显的问题,就是阴影不完整,这个时候,我们可以通过调整相机的实际范围来增加阴影的生成区域

控制正交相机的6个要素,分别为 left,right,top,bottom,near, far

正交相机在之前的相机篇已经做了介绍,不懂的可以回顾一下【ThreeJS基础教程-初识Threejs】1.5 选择合适的相机与相机切换

首先我们得知道,默认的值是多少
在这里插入图片描述
在这里插入图片描述

从侧面拉远了之后,我们看到,物体并没有超出near和far的范畴,所以near和far此时不需要更改

在这里插入图片描述
从正面看,明显比物体小一圈,所以我们此时把left,right,top,bottom都翻一倍即可

        directionalLight.shadow.camera.left = -10;directionalLight.shadow.camera.right = 10;directionalLight.shadow.camera.top = 10;directionalLight.shadow.camera.bottom = -10;

在这里插入图片描述
这时,我们的阴影就正常了

点光源阴影

我们将上述代码,替换 addLight() 的部分

    function addLight() {let pointLight = new THREE.PointLight(0xffffff,1.0,40,0.1);pointLight.position.set(0,20,20);pointLight.castShadow = true;console.log(pointLight);let pointLightHelper = new THREE.PointLightHelper(pointLight,1,0xff0000);let cameraHelper = new THREE.CameraHelper(pointLight.shadow.camera);scene.add(pointLight);scene.add(pointLightHelper);scene.add(cameraHelper);}

在这里插入图片描述
在这里插入图片描述

官方对于点光源阴影的介绍实在太过简单。。。

点光源实际使用透视相机来计算阴影,但是我们实际上通过透视相机辅助线并不能看到透视相机的变化,这个原因就由你们自行研究了

可以说的是,点光源的阴影也是有范围的,且范围跟随distance属性的变化而变化,我们在代码中,把distance设置到了40,并没有完全覆盖物体后面的光影区域,所以不仅照不亮那一块,连阴影也不会产生

我们修改了distance后,达到了比较好的效果

在这里插入图片描述
可以看得出,点光源的阴影,是会随着距离点光源的距离,而越来越大,与现实中的灯泡是完全一致的

聚光灯阴影

//和上面一样,我们依然修改addLight()即可function addLight() {//聚光灯的属性这里不再赘述let spotLight = new THREE.SpotLight(0xffffff,10,50,0.5,0.2,0.2);spotLight.castShadow = true;spotLight.position.set(0,20,20);let spotLightHelper = new THREE.SpotLightHelper(spotLight,0xff0000);scene.add(spotLight);scene.add(spotLightHelper);}

在这里插入图片描述
聚光灯内部也是使用透视相机进行阴影计算的,和点光源的越远阴影越大一样

如果想对聚光灯调节照射范围,只需要修改distance,angle,等属性即可,无需像上面平行光一样需要手动修改相机

优化阴影

以下方案对上述所有光源均有效

阴影范围外一片漆黑,可以优化一下吗

我们以刚写完的聚光灯案例入手,其实我们只需要加一个亮度不高的环境光,效果就会好很多
这样,即使物体不处在聚光灯光源之下,也能看清楚物体

        scene.add(new THREE.AmbientLight(0xffffff,0.2));

在这里插入图片描述

一般情况下,场景中是需要一个全局光照的,这个全局光照,可以是一个纯环境光,也可以是一个半球光,根据自己的需求来设置即可,这样开启阴影后,就不会产生某个地方特别漆黑的情况,也能有比较贴近现实的感觉,环境光亮度根据自己的实际需求来调节即可

增加阴影的精度

阴影的本质,其实就是计算一块阴影,然后覆盖到物体的原有的贴图上

所以阴影也是有纹理的性质的,比如说分辨率
如果你的阴影效果比较差,可以使用下面的方式来提高阴影精度

	//建议两个参数值相等,且数值为2的幂次倍// 如: 256 * 256,512 * 512,1024 * 1024,2048 * 2048light.shadow.mapSize.set(512,512);

由于在demo中,修改此值没有太大区别,所以这里不做演示了

注意:提高了一倍的阴影精度,计算量大约会增加4倍,最高仅建议到4096

消除伪影

摩尔纹效果图来自百度
摩尔纹效果来源百度,如有侵权请联系笔者

有时候阴影会出现类似上图的摩尔纹效果,可以用调整bias来解决

笔者刚才在尝试的过程中,没有一次能复现摩尔纹效果,所以这里仅找一张百度的图片来代替演示效果,实际上

在这里插入图片描述

	light.shadow.bias -= 0.0001;

静态阴影渲染 / 渐进式阴影渲染

Threejs官方案例shadowmap_progressive

这里的光影,我们可以从效果中看到,阴影不是第一时间渲染完成的,而是在物体或灯光移动后的几秒钟后完成的,这种阴影渲染叫:静态光影渲染,或渐进式阴影渲染

这种渲染的好处是,我们不需要实时的去更新阴影,只需要在改变物体的一瞬间重新渲染光影即可

这种阴影渲染可以用在不经常移动的物体上

具体的实现方式,请自行查看threejs官方案例的源代码

烘培阴影

烘培阴影已经在上一篇做了简单介绍,这里就不再赘述了
【Threejs基础教程-光影篇】5.1 常用的灯光

使用阴影时需要注意的点

  1. 阴影计算非常消耗性能,要根据实际需求去决定如何使用阴影渲染
  2. 你的模型已经很大的情况下,不推荐使用实时阴影
  3. 减少产生阴影的灯光,产生阴影的光源越多,也会呈指数级的额外消耗性能

Threejs基础教程在此完结,后续请查阅本人的: Threejs进阶教程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/783742.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

判断一个数据能否同时被3和5整除

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int a 0;//提示用户printf("请输入一个整数\n");//获取用户输入数据&#xff1b;scanf("%d", &am…

Spring Boot项目启动过程中为什么日志打印没有显示完整包名呢?

一、前言 不知道大家注意过没有&#xff0c;在Spring Boot项目启动过程中日志打印并没有显示完整的报名&#xff0c;而是显示一些o.a.c&#xff0c;o.s.web形式的包名&#xff0c;如下图&#xff1a; 这是为什么呢&#xff1f; 二、原理 首先&#xff0c;我们先看一下Spring…

WordPress AutomaticPlugin SSRF漏洞复现(CVE-2024-27954)

0x01 产品简介 WordPress是一款免费开源的内容管理系统(CMS),最初是一个博客平台,但后来发展成为一个功能强大的网站建设工具,适用于各种类型的网站,包括个人博客、企业网站、电子商务网站等,并逐步演化成一款内容管理系统软件。 0x02 漏洞概述 WordPress AutomaticPlu…

01-XML-04XML处理

XML处理 DOM DOM解析要求解析器将整个XML文件全部加载到内存中&#xff0c;生成一个Document对象。 优点&#xff1a;元素和元素之间保留结构&#xff0c;关系&#xff0c;可以针对元素进行增删改查操作。 缺点&#xff1a;如果XML文件过大&#xff0c;可能会导致内存溢出。SA…

【QT入门】 QListWidget各种常见用法详解之列表模式

往期回顾 【QT入门】 Qt代码创建布局之setLayout使用-CSDN博客 【QT入门】 Qt代码创建布局之多重布局变换与布局删除技巧-CSDN博客 【QT入门】 QTabWidget各种常见用法详解-CSDN博客 【QT入门】 QListWidget各种常见用法详解之列表模式 QListWidget有列表和图标两种显示模式&a…

springboot论坛管理系统

论坛管理系统 摘要&#xff1a; 在社会快速发展的影响下&#xff0c;论坛管理系统继续发展&#xff0c;使论坛管理系统的管理和运营比过去十年更加信息化。依照这一现实为基础&#xff0c;设计一个快捷而又方便的网上论坛管理系统是一项十分重要并且有价值的事情。对于传统的论…

一篇讲明白 Hadoop 生态的三大部件

文章目录 每日一句正能量前言01 HDFS02 Yarn03 Hive04 HBase05 Spark及Spark Streaming关于作者推荐理由后记赠书活动 每日一句正能量 黎明时怀着飞扬的心醒来&#xff0c;致谢爱的又一天&#xff0c;正午时沉醉于爱的狂喜中休憩&#xff0c;黄昏时带着感恩归家&#xff0c;然后…

【Linux】进程实践项目 —— 自主shell编写

送给大家一句话&#xff1a; 不管前方的路有多苦&#xff0c;只要走的方向正确&#xff0c;不管多么崎岖不平&#xff0c;都比站在原地更接近幸福。 —— 宫崎骏《千与千寻》 自主shell命令编写 1 前言2 项目实现2.1 创建命令行2.2 获取命令2.3 分割命令2.4 运行命令 3 源代码…

非NVIDIA平台下的CUDA的替代方案OpenCL,第一步如何获取PlatformInfo、DeviceInfo

非NVIDIA平台下的CUDA的替代方案OpenCL&#xff0c;第一步如何获取PlatformInfo、DeviceInfo 介绍 当谈到高性能计算&#xff0c;NVIDIA的CUDA框架无疑是一个强大的工具。OpenC&#xff08;Open Computing Language&#xff09;是一个更为通用的解决方案&#xff0c;或者你使用…

Vscode连接远程服务器中的docker容器进行开发

0.预安装 1.本地windows或其他环境中安装了Vscode&#xff0c;Vscode中安装了Remote-SSH拓展&#xff08;用于利用SSH连接docker容器&#xff09; 2.远程服务器中安装了docker&#xff0c;并且拉取了自己需要的镜像 3.有root权限&#xff0c;能使用sudo命令 1. 在服务器端启…

javaWeb项目-学生考勤管理系统功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、JAVA技术 JavaSc…

蓝桥杯省赛刷题——题目 2656:刷题统计

刷题统计OJ链接&#xff1a;蓝桥杯2022年第十三届省赛真题-刷题统计 - C语言网 (dotcpp.com) 题目描述 小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 a 道题目&#xff0c;周六和周日每天做 b 道题目。请你帮小明计算&#xff0c;按照计划他将在第几…

MS Edge浏览器坏了?网页播放视频的速度不对

前言 小白是MS Edge浏览器的重度用户。电脑上必须有的两个浏览器&#xff1a;Google Chrome和Microsoft Edge。 前段时间小白在使用MS Edge的时候出了问题&#xff1a;播放视频或者音频的时候总是被莫名其妙加速或者减速&#xff0c;类似于播放视频时候的0.5x或者2.0x。 当时…

C++入门知识详细讲解

C入门知识详细讲解 1. C简介1.1 什么是C1.2 C的发展史1.3. C的重要性1.3.1 语言的使用广泛度1.3.2 在工作领域 2. C基本语法知识2.1. C关键字(C98)2.2. 命名空间2.2 命名空间使用2.2 命名空间使用 2.3. C输入&输出2.4. 缺省参数2.4.1 缺省参数概念2.4.2 缺省参数分类 2.5. …

Abaqus周期性边界代表体单元Random Sphere RVE 3D (Mesh)插件

插件介绍 Random Sphere RVE 3D (Mesh) - AbyssFish 插件可在Abaqus生成三维具备周期性边界条件(Periodic Boundary Conditions, PBC)的随机球体骨料及骨料-水泥界面过渡区(Interfacial Transition Zone, ITZ)模型。即采用周期性代表性体积单元法(Periodic Representative Vol…

python distribute是什么

Python的包管理工具常见的有easy_install, setuptools, 还有pip, distribute&#xff0c;那麽这几个工具有什么关系呢&#xff0c;看一下下面这个图就明白了&#xff1a; 可以看到distribute是setuptools的替代方案&#xff0c;pip是easy_install的替代方案。 Distribute提供一…

【QT学习】2.补充:connect中的lambda表达式

一.简单实例&#xff1a; 1.实例要求 点击按钮&#xff0c;实现 >o<与#-#的转换。 2.步骤 补充&#xff1a;​​​​​​​ 1.如果我想在lambda中修改数据&#xff0c;怎么办&#xff1f; 写上mutable就行。

vue基础教程(5)——构建项目级登录页

同学们可以私信我加入学习群&#xff01; 正文开始 前言一、创建首页二、登录页代码讲解三、对应的vue知识点&#xff1a;四、附件-各文件代码总结 前言 前面我们已经把vue自带的页面删除&#xff0c;也搭建了最简单的router路由&#xff0c;下面就可以真正开发我们自己的项目…

【独立开发前线】Vol.29 专注于电子邮件签名,也可以依靠SEO年入70万美元

今天要给大家分享的案例是MySignature&#xff0c;一个专注于电子邮件签名的产品&#xff1b; 它的官网是&#xff1a;MySignature: Free Email Signature Generator 提到电子邮件签名&#xff0c;很多人想到的肯定是“那不是电子邮件结尾的几行图文介绍吗&#xff0c;这也能做…

ZNC3罗德与施瓦茨ZNC3网络分析仪

181/2461/8938产品概述&#xff1a; 罗德与施瓦茨 ZNC3 网络分析仪的工作频率范围为 9 kHz 至 3 GHz&#xff0c;面向移动无线电和电子产品行业的应用。它具有双向测试装置&#xff0c;用于测量有源和无源 DUT 的所有四个 S 参数。此外&#xff0c;它还提供适合开发和生产中各…