Three 光源 (总结四)

萤火虫飞舞

import * as THREE from 'three'
import { OrbitControls } from '../../js/jsm/controls/OrbitControls.js'; // 引入相机控件

let scene, camera, renderer, controls, flyBall, ball
function init() {
  scene = new THREE.Scene()
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
  camera.position.set(5, 5, 5)
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setSize(window.innerWidth, window.innerHeight)
  document.body.appendChild(renderer.domElement)

  controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true

  const axesHelper = new THREE.AxesHelper(5)
  scene.add(axesHelper)
  // 1. 渲染器开启阴影支持(性能消耗高)
  renderer.shadowMap.enabled = true
}


function createBall(){
  const geometry = new THREE.SphereGeometry(1, 32, 16)
  const material = new THREE.MeshStandardMaterial({
    color: 0x00ff00
  })
  ball = new THREE.Mesh(geometry, material)
  ball.position.set(0, 1, 0)
  scene.add(ball)

  ball.castShadow = true
}

// 目标:练习-萤火虫飞舞
// 1. 创建纯颜色小球体
// 2. 使用点光源,并加入到小球体上
// 3. 在渲染循环,不断修改小球体位移坐标实现旋转跳跃效果
function createFlyBall() {
  const geometry = new THREE.SphereGeometry(0.1, 32, 16)
  const material = new THREE.MeshBasicMaterial({
    color: 0x99ff00
  })
  flyBall = new THREE.Mesh(geometry, material)
  flyBall.position.set(3, 3, 3)
  scene.add(flyBall)
}
function createLight() {
  const directionalLight = new THREE.PointLight(0x99ff00, 5);
  directionalLight.target = ball;
  directionalLight.castShadow = true;

  // 2. 使用点光源,并加入到小球体上
  // 关键1:灯光在到球的位置(光就会跟着球体一起动)
  // 关键2:灯光不要再设置偏移位置了(位移是参考父级物体的-就是加到的球体中心点进行偏移)
  flyBall.add(directionalLight);
}
function render(t) {
  renderer.render(scene, camera)
  // 3. 在渲染循环,不断修改小球体位移坐标实现旋转跳跃效果
  
  // t 是毫秒值,转换成秒,正弦范围 -1.0 到 1.0 (随着传入的值增大,得到的值在这个范围反复横跳)
  // 乘以 3 就是 -3 到 3 之间运动
  flyBall.position.x = Math.cos(t / 1000) * 3 
  // 余弦范围 -1.0 到 1.0
  flyBall.position.z = Math.sin(t / 1000) * 3 
  // 乘以 0.5 就是范围移动小一些(y 轴默认晚上偏移一些,所以 + 3)
  flyBall.position.y = 3 + Math.sin(t / 100) * 0.5

  // 注意:x 用 cos,z 用 sin 就变成了顺时针旋转
  requestAnimationFrame(render)
}

init()
createBall()
createFlyBall()
createLight()
render()

(环境光)AmbientLight

环境光会均匀的照亮场景中的所有物体。环境光不能用来投射阴影,因为它没有方向。

AmbientLight( color : Integer, intensity : Float )

属性

#.castShadow : Boolean

这个参数在对象构造的时候就被设置成了 undefined 。因为环境光不能投射阴影。

#.isAmbientLight : Boolean

用来校验这个类或者派生类是不是环境光.默认是 true

目标:使用环境光+标准网格材质,创建一个平面模拟地面效果

1. 创建平面缓冲几何体

2. 创建环境光

//注意1:没有方向,不能投射阴影,只能照亮物体,没有光斑

//注意2:材质是白色,为何不是纯白色而变成灰色了?(因为材质为标准网格材质-需要参考光照的影响一起计算后再绘制每个像素点颜色)
function createFloor(){
  // 1. 创建平面缓冲几何体
  const geometry = new THREE.PlaneGeometry(10,10);
  const material = new THREE.MeshStandardMaterial({
    color: 0xffffff,
    side: THREE.DoubleSide
  })
  const plane = new THREE.Mesh(geometry,material);
  plane.rotation.set(-Math.PI / 2, 0, 0);
  scene.add(plane)
}
function createLight(){
  const light = new THREE.AmbientLight(0xffffff,1)
  scene.add(light)
}

 

 平行光(DirectionalLight)

平行光是沿着特定方向发射的光。这种光的表现像是无限远,从它发出的光线都是平行的。常常用平行光来模拟太阳光 的效果; 太阳足够远,因此我们可以认为太阳的位置是无限远,所以我们认为从太阳发出的光线也都是平行的。

DirectionalLight( color : Integer, intensity : Float )

color - (可选参数) 16进制表示光的颜色。 缺省值为 0xffffff (白色)。
intensity - (可选参数) 光照的强度。缺省值为1。

 属性

# .castShadow : Boolean

如果设置为 true 该平行光会产生动态阴影。 警告: 这样做的代价比较高而且需要一直调整到阴影看起来正确。该属性默认为 false

const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(3, 3, 3);
scene.add(directionalLight);
directionalLight.castShadow = true

# .isDirectionalLight : Boolean

用来校验这个类或者派生类是不是平行光.默认是 true

不应该去改变这个变量,因为内部使用这个变量做了些优化的工作。

# .position : Vector3

假如这个值设置等于 Object3D.DefaultUp (0, 1, 0),那么光线将会从上往下照射。

# .shadow : DirectionalLightShadow

这个 DirectionalLightShadow 对象用来计算该平行光产生的阴影。

# .target : Object3D

平行光的方向是从它的位置到目标位置。默认的目标位置为原点 (0,0,0)
注意: 对于目标的位置,要将其更改为除缺省值之外的任何位置,它必须被添加到 scene 场景中去。

1. 创建 DirectionalLight 平行光对象,设置位置等添加到场景中

2. 创建 DirectionalLightHelper 平行光辅助对象(可选),辅助我们观察光源位置

// 疑惑:与环境光区别?
// 解答:平行光可以产生光斑,给地面粗糙度设置为 0 旋转摄像机角度查看效果
function createLight(){
  // 1. 创建 DirectionalLight 平行光对象,设置位置等添加到场景中
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1, 50);
  directionalLight.position.set(5,5,5);
  scene.add(directionalLight);

 // 2. 创建 DirectionalLightHelper 平行光辅助对象(可选),辅助我们观察光源位置
  const helper = new THREE.DirectionalLightHelper(directionalLight,1)
  scene.add(helper)
}

 

点光源(PointLight) 

从一个点向各个方向发射的光源。一个常见的例子是模拟一个灯泡发出的光。

PointLight( color : Integer, intensity : Float, distance : Number, decay : Float )

color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。
intensity - (可选参数) 光照强度。 缺省值 1。

distance - 这个距离表示从光源到光照强度为0的位置。 当设置为0时,光永远不会消失(距离无穷大)。缺省值 0.
decay - 沿着光照距离的衰退量。缺省值 1。 在 physically correct 模式中,decay = 2。

属性 

# .decay : Float

沿着光照距离的衰减量
在 physically correct 模式下,decay 设置为等于2将实现现实世界的光衰减。缺省值为 1

# .distance : Float

如果非零,那么光强度将会从最大值当前灯光位置处按照距离线性衰减到0。 缺省值为 0.0

# .isPointLight : Boolean

用来校验这个类或者派生类是不是点光源。默认是 true

不应该去改变这个变量,因为内部使用这个变量做了些优化的工作。

# .shadow : LightShadow

LightShadow用与计算此光照的阴影。

1. 创建 PointLight 点光源对象

2. 创建 PointLightHelper 辅助对象观察所在位置

// 注意:距离光源越远地方越暗

function createLight(){
  // 1. 创建 PointLight 点光源对象、
  // 参数3:光源照射的最大距离。默认值为 0(无限远)
  const pointLight = new THREE.PointLight(0xffffff, 1, 50);
  pointLight.position.set(5,5,5);
  scene.add(pointLight);

  // 2. 创建 PointLightHelper 辅助对象观察所在位置
  const pointLightHelper = new THREE.PointLightHelper(pointLight,1)
  scene.add(pointLightHelper)
}

聚光灯(SpotLight)

聚光灯是从一个方向上的一个点发出,沿着一个圆锥体,它离光越远,它的尺寸就越大。

SpotLight( color : Integer, intensity : Float, distance : Float, angle : Radians, penumbra : Float, decay : Float )

color - (可选参数) 十六进制光照颜色。 缺省值 0xffffff (白色)。
intensity - (可选参数) 光照强度。 缺省值 1。

distance - 从光源发出光的最大距离,其强度根据光源的距离线性衰减。
angle - 光线散射角度,最大为Math.PI/2。
penumbra - 聚光锥的半影衰减百分比。在0和1之间的值。默认为0。
decay - 沿着光照距离的衰减量。

属性 

# .angle : Float

从聚光灯的位置以弧度表示聚光灯的最大范围。应该不超过 Math.PI/2。默认值为 Math.PI/3

# .castShadow : Boolean

此属性设置为 true 聚光灯将投射阴影。警告: 这样做的代价比较高而且需要一直调整到阴影看起来正确。 查看 SpotLightShadow 了解详细信息。 默认值为 false

# .decay : Float

沿着光照距离的衰减量
在 physically correct 模式下,decay 设置为等于2将实现现实世界的光衰减。
缺省值为 1

# .distance : Float

如果非零,那么光强度将会从最大值当前灯光位置处按照距离线性衰减到0。 缺省值为 0.0

# .isSpotLight : Boolean

用来校验这个类或者它的派生类是不是聚光灯光源。缺省值是 true

不应该去改变这个变量,因为内部使用这个变量做了些优化的工作。

# .penumbra : Float

聚光锥的半影衰减百分比。在0和1之间的值。 默认值 — 0.0。

# .position : Vector3

假如这个值设置等于 Object3D.DefaultUp (0, 1, 0),那么光线将会从上往下照射。

1. 创建 SpotLight 聚光灯对象,设置位置等添加到场景中

2. 创建 SpotLightHelper 聚光灯辅助对象(可选),辅助我们观察光源位置

function createLight(){
  // 1. 创建 SpotLight 聚光灯对象,设置位置等添加到场景中
  // 强度设置高一些,纹理看的清楚
  const spotLight = new THREE.SpotLight(0xffffff, 15);
  spotLight.position.set(5,5,5);

  // 灯光的纹理(会把图片和聚光灯颜色混合后打在目标物体上)
  spotLight.map = new THREE.TextureLoader().load('../image/desert.jpg');

  // 灯光的角度(0 - Math.PI / 2)
  spotLight.angle = 0.16*Math.PI;

  // 光的衰减程度(0-1)让光斑周围虚化程度(0 不要)
  spotLight.penumbra = 0.8;
  scene.add(spotLight)

 // 2. 创建 SpotLightHelper 平行光辅助对象(可选),辅助我们观察光源位置
  const helper = new THREE.SpotLightHelper(spotLight,1)
  scene.add(helper)

  // 补充:使用 GUI 工具调整查看具体效果
  const gui = new GUI();
  gui.add(spotLight, 'intensity', 0, 15, 0.1).name('光照强度')
  gui.add(spotLight, 'distance', 0, 15, 0.1).name('光照距离').onChange(() => {
    helper.update()
  })
  gui.add(spotLight, 'angle', 0, Math.PI / 2, 0.1).name('光照角度').onChange(() => {
    helper.update()
  })
  gui.add(spotLight, 'penumbra', 0, 1, 0.1).name('半影衰减').onChange(() => {
    helper.update()
  })
  // 距离越远越暗
  // 低版本可能需要设置:渲染器对象.physicallyCorrectLights = true (开启物理衰减模式)
  gui.add(spotLight, 'decay', 0, 5, 0.1).name('衰减距离').onChange(() => {
    helper.update()
  })
}

灯光与阴影 

点光源与阴影   或平行光与阴影

聚光灯与阴影 

阴影细节修改 

// 目标:阴影细节修改
function createLight() {
  // 平行光(太阳)
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  directionalLight.position.set(3, 3, 3);
  scene.add(directionalLight);

  directionalLight.castShadow = true

  // 1. 模糊阴影的边缘(如果贴图宽高不够,会出现马赛克)
  directionalLight.shadow.radius = 15
  // 2. 阴影贴图的宽度和高度(要求是 2 的幂)
  directionalLight.shadow.mapSize.set(1024, 1024)

  // 3. 可以通过控制光源摄像机影响阴影的大小效果
  // 设置光投射相机的属性(光的位置就是正交相机位置)
  // 用于干涉计算阴影的范围,超出摄像机长方体外的物体不计算阴影
  directionalLight.shadow.camera.near = 0.5
  directionalLight.shadow.camera.far = 20
  // 这个会围成一个长方体范围空间
  directionalLight.shadow.camera.left = -5
  directionalLight.shadow.camera.right = 5
  directionalLight.shadow.camera.top = 5
  directionalLight.shadow.camera.bottom = -5

  const helper = new THREE.DirectionalLightHelper(directionalLight, 1);
  scene.add(helper);
}

照射指定物体

function createLight() {
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  directionalLight.position.set(3, 3, 3);
  scene.add(directionalLight);
  // 2. 设置光源对象.target 赋予球体
  directionalLight.target = ball

  const helper = new THREE.DirectionalLightHelper(directionalLight, 1);
  scene.add(helper);

  // 移动球,看看光源是否跟随移动
  gui.add(ball.position, 'x', 0, 5, 0.1).name('移动球体').onChange(() => {
    helper.update() // 更新辅助对象
  })
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

幸福金龄会第二届《锦绣中华》中老年文旅文化艺术节圆满落幕

广东,这片承载着深厚文化底蕴的土地,再次见证了中老年文化艺术的璀璨盛放。近日,由幸福金龄会主办、广之旅协办的第二届《锦绣中华》中老年文旅文化艺术节在广东隆重举行。活动汇聚了广东各支文艺团队,他们用最真挚的表演&#xf…

讲述微信小程序 通信模型

之前的文章 讲述微信小程序宿主环境 我们讲到了 手机微信 为小程序 提供了多方面支持 包括 1 通讯模型 2 运行机制 3 组件 4 API 今天 我们就来说 通讯模型 小程序中的 通信主题 是 渲染层 和 逻辑层 首先 渲染层中 包含的是 wxml 页面模板 和 wxss样式 逻辑层 里面则都是js的…

如何从视频中提取gif?仅需三步在线制作

视频提取GIF是一种常见的图像处理技术,它可以将视频中的某一段或某一帧提取出来,并保存为GIF格式的动图。这种技术在互联网上广泛应用,成为了分享精彩瞬间和制作有趣动画的有力工具。想要从视频中截取动图,使用视频转gif工具&…

超越标签的探索:K-means与DBSCAN在数据分析中的新视角

最近在苦恼为我的数据决定分组问题,在查找资料时,恰好看到机器学习中的无监督学习的聚类分析,正好适用于我的问题,但是我之前学机器学习时。正好没有学习无监督部分,因为我认为绝大多数问题都是有标签的监督学习&#…

IPSEC VPN-详解原理

目录 IPSEC提供的安全服务 IPSEC协议簇 ​编辑 安全协议 1.传输模式 2. 隧道模式 AH ---鉴别头协议 AH提供的安全服务: AH头部 AH的保护范围 1.传输模式 2.隧道模式 ​编辑 ESP ---封装安全载荷协议 ESP提供的安全服务: ESP的头部 ESP的保护范围 1.传输…

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程

在讲进程之前首先就是需要去回顾一下我们之前学的操作系统是干嘛的,首先操作系统是一个软件,它是对上提供一个良好高效,稳定的环境的,这是相对于用户来说的,对下是为了进行更好的软硬件管理的,所以操作系统…

es文档操作命令

文档操作 documents 创建数据(put) 向 user 索引下创建3条数据 PUT /user/_doc/1 {"name":"zhangsan","age":18,"sex":"男","info":"一顿操作猛如虎,一看工资2500"…

关于卷积神经网络特征可视化

卷积神经网络CNN,一个大号/深层的,现代的,黑箱的,信号/图像处理器。 简单讲解如何将图像输入到卷积神经网络CNN并显示网络不同层的激活图,并通过将激活图与原始图像进行比较以探索网络学习哪些特征 本例来源于Mathwo…

IP代理技术革新:探索数据采集的新路径

引言: 随着全球化进程不断加深,网络数据采集在企业决策和市场分析中扮演着愈发重要的角色。然而,地域限制和IP封锁等问题常常给数据采集工作带来了巨大挑战。亿牛云代理服务凭借其强大的网络覆盖和真实住宅IP资源,成为解决这些问…

大A为何频繁跳水,Python量化1200W条交易数据给你答案!| 邢不行

这是邢不行第 110 期量化小讲堂的分享 作者 | 邢不行、密斯锌硒 常看我文章的读者应该能发现,我介绍过的量化策略大多都会在开盘时买入。 比如小市值策略和散户反着买策略: 小市值策略文章 散户反着买策略 它们都会在每个周期的第一个交易日开盘去…

Git Bash命令初始化本地仓库,提交到远程仓库

git init:初始化空仓库 // 初始化一个空仓库或者重新初始化一个存在的仓库 git init git remote // 为当前本地仓库添加一个远程仓库地址 git remote add origin https://gitee.com/xxx/demo.git git pull // 从设置好链接的远程仓库拉去已经存在的数据,…

Python自动化测试——postman,jmeter接口测试

关于众所postman,jmeter,做自动化测试的我想对这两个词并不陌生。大家都知道postman用来做接口测试很方便,下面我们就用一些例子来演示一下它该如何进行接口测试: 首先我们来介绍一下接口测试的概念: 1、什么是接口测试&#xf…

被围绕的区域c++

题目 链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 输入 4 4 XXXX XOOX XOXX XXOX输出 XXXX XXXX XXXX XXOX思路 由题知边界上的"O"和 与边界的"O"相连的"O"不会被标记,我们可以用一个数组st[][]标…

SpringBoot项目如何打包成war包,并部署在tomcat上运行

项目场景: 正常情况下,我们开发 SpringBoot 项目,由于内置了Tomcat,所以项目可以直接启动,部署到服务器的时候,直接打成 jar 包,就可以运行了。 有时我们会需要打包成 war 包,放入外…

23.1 微服务理论基础

23.1 微服务基础 1. 微服务介绍2. 微服务特点3. 微服务优缺点4. 微服务两大门派5. 微服务拆分6. 微服务扩展6.1 服务扩展6.2 按需扩展7. 微服务重要模块******************************************************************************************************************

【华为Datacom数通认证】HCIA-HCIP-HCIE

华为认证课程概述 华为认证是华为技术有限公司(简称"华为")基于"平台生态"战略,围绕"云-管-端"协同的新ICT技术架构,打造的业界覆盖ICT领域最广的认证体系,包含"ICT技术架构认证"、"ICT开发者…

【鸿蒙HarmonyOS开发笔记】动画过渡效果之布局更新动画

概述 动画的原理是在一个时间段内,多次改变UI外观,由于人眼会产生视觉暂留,所以最终看到的就是一个“连续”的动画。UI的一次改变称为一个动画帧,对应一次屏幕刷新,而决定动画流畅度的一个重要指标就是帧率FPS&#x…

怎么看一手伦敦银多少钱?

做伦敦银投资的朋友需要搞清楚“一手伦敦银多少钱”的问题,这也是伦敦银交易的基础问题。为什么需要搞清楚这个基础问题呢?有些基础问题我们不需要搞懂,但是关于一手伦敦银多少钱却需要搞清楚,因为这决定了投资者的资金利用率。 关…

Java-Java基础学习(1)-重写和多态对比分析

Java中的重写(Override)和多态(Polymorphism)是两个核心概念,它们在面向对象编程中扮演着非常重要的角色。下面我将对这两个概念进行详细的对比分析,包括它们的区别、联系以及应用场景,并附上相…

为什么关掉了公众号留言功能?

为什么公众号没有留言功能?根据要求,自2018年2月12日起,新申请的微信公众号默认无留言功能。有些人听过一个说法:公众号粉丝累计到一定程度或者原创文章数量累计到一定程度就可以开通留言功能。其实这个方法是2018年之前才可以&am…