Threejs_13 聚光灯和点光源的使用

聚光灯就如同手电筒一样,点光源就如同一个电灯泡甚至是萤火虫那样。如何使用他们呢?

我们还是一样,先做一个小球和一个平面,用来展示光线。并且加入基本的环境光。

// 做一个球体
const SphereGeometry = new THREE.SphereGeometry(1, 20, 20);
// 材质
const material = new THREE.MeshStandardMaterial();
const sphere = new THREE.Mesh(SphereGeometry, material);
// 投射阴影
sphere.castShadow = true;
scene.add(sphere);

// 创建平面
const planeGeometry = new THREE.PlaneGeometry(50, 50);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
// 接收阴影
plane.receiveShadow = true;
scene.add(plane);

// 灯光
// 环境光
const light = new THREE.AmbientLight(0xffffff);

scene.add(light);

聚光灯

Threejs 聚光灯手册

使用聚光灯就将之前的直线光源换成聚光灯就可以,当然,聚光灯有一些新的属性,比如说角度、衰减、半影衰减、沿着光照距离衰减等。我们可以直接使用gui做测试。

// 聚光源
const spotLight = new THREE.SpotLight(0xffffff, 2);
spotLight.position.set(5, 5, 5);
spotLight.intensity = 2;
// 设置直线光源产生阴影
spotLight.castShadow = true;
//设置阴影贴图模糊度
spotLight.shadow.radius = 20;
//设置阴影贴图的分辨率(让它变得更加细致)
spotLight.shadow.mapSize.set(4096, 4096);
//设置打在小球上
spotLight.target = sphere;
//聚光灯的角度
spotLight.angle = Math.PI / 6;
//聚光灯的衰减
spotLight.distance = 0;
//聚光灯的半影的衰减
spotLight.penumbra = 0.5;
//聚光灯 沿着光照距离的衰减
spotLight.decay = 0;
// 透视相机的属性设置(一般不用更改)

scene.add(spotLight);

gui.add(sphere.position, "x").min(-5).max(5).step(0.1);
gui
  .add(spotLight, "angle")
  .min(0)
  .max(Math.PI / 2)
  .step(0.01);
gui.add(spotLight, "distance").min(0).max(10).step(0.1);
gui.add(spotLight, "penumbra").min(0).max(10).step(0.1);
gui.add(spotLight, "decay").min(0).max(1).step(0.1);

这里我们要注意,需要将我们的物理渲染器打开

//开启物理渲染器
renderer.physicallyCorrectLights = true;

聚光灯全部代码

//点光源(灯泡) 和 聚光灯(手电筒)
//导入 threejs
import * as THREE from "three";
//导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
//导入lil.gui
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
// 创建场景
const scene = new THREE.Scene();

// 创建相机
const camera = new THREE.PerspectiveCamera(
  45, // 视角
  window.innerWidth / window.innerHeight, // 宽高比 窗口的宽高进行设置的
  0.1, // 近平面   相机最近最近能看到的物体
  1000 // 远平面   相机最远能看到的物体
);

//设置相机位置
camera.position.set(0, 0, 10);

scene.add(camera);

// 创建渲染器
const renderer = new THREE.WebGLRenderer();

// 设置渲染器的大小  (窗口大小)
renderer.setSize(window.innerWidth, window.innerHeight);

// 开启场景中的阴影贴图
renderer.shadowMap.enabled = true;

//开启物理渲染器
renderer.physicallyCorrectLights = true;

// 将渲染器的dom元素添加到body中
document.body.appendChild(renderer.domElement);

//添加世界坐标辅助器  (红色x轴,绿色y轴,蓝色z轴)一个线段 参数为 线段长度
const axesHelper = new THREE.AxesHelper(6);

//添加到场景之中
scene.add(axesHelper);

// 添加轨道控制器 (修改侦听位置)  一般监听画布的事件  不监听document.body
const controls = new OrbitControls(camera, renderer.domElement);

//渲染函数
function animate() {
  controls.update();
  //请求动画帧
  requestAnimationFrame(animate);
  //渲染
  renderer.render(scene, camera);
}

//渲染
animate();

// 监听窗口的变化 重新设置渲染器的大小 画布自适应窗口
window.addEventListener("resize", () => {
  // 重新设置渲染器的大小
  renderer.setSize(window.innerWidth, window.innerHeight);
  // 重新设置相机的宽高比
  camera.aspect = window.innerWidth / window.innerHeight;
  // 重新计算相机的投影矩阵
  camera.updateProjectionMatrix();
});
//创建gui实例
const gui = new GUI();

// 做一个球体
const SphereGeometry = new THREE.SphereGeometry(1, 20, 20);
// 材质
const material = new THREE.MeshStandardMaterial();
const sphere = new THREE.Mesh(SphereGeometry, material);
// 投射阴影
sphere.castShadow = true;
scene.add(sphere);

// 创建平面
const planeGeometry = new THREE.PlaneGeometry(50, 50);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
// 接收阴影
plane.receiveShadow = true;
scene.add(plane);

// 灯光
// 环境光
const light = new THREE.AmbientLight(0xffffff);

// 聚光源
const spotLight = new THREE.SpotLight(0xffffff, 2);
spotLight.position.set(5, 5, 5);
spotLight.intensity = 2;
// 设置直线光源产生阴影
spotLight.castShadow = true;
//设置阴影贴图模糊度
spotLight.shadow.radius = 20;
//设置阴影贴图的分辨率(让它变得更加细致)
spotLight.shadow.mapSize.set(4096, 4096);
//设置打在小球上
spotLight.target = sphere;
//聚光灯的角度
spotLight.angle = Math.PI / 6;
//聚光灯的衰减
spotLight.distance = 0;
//聚光灯的半影的衰减
spotLight.penumbra = 0.5;
//聚光灯 沿着光照距离的衰减
spotLight.decay = 0;
// 透视相机的属性设置(一般不用更改)

scene.add(spotLight);
scene.add(light);
gui.add(sphere.position, "x").min(-5).max(5).step(0.1).name("球体x轴位置");
gui
  .add(spotLight, "angle")
  .min(0)
  .max(Math.PI / 2)
  .step(0.01)
  .name("聚光灯角度");
gui.add(spotLight, "distance").min(0).max(10).step(0.1).name("聚光灯距离");
gui.add(spotLight, "penumbra").min(0).max(10).step(0.1).name("聚光灯半影");
gui.add(spotLight, "decay").min(0).max(1).step(0.1).name("聚光灯衰减");

点光源

Threejs 点光源手册

点光源就相当于我们生活中的萤火虫 或者电灯泡。这里我们直接将聚光灯的代码换成点光源。

聚光灯中的部分属性在点光源中是没有的,比如说角度,半影。

const pointLight = new THREE.PointLight(0xff0000, 2);
pointLight.position.set(2, 2, 2);

//光照强度
// pointLight.intensity = 2;
// 设置直线光源产生阴影
pointLight.castShadow = true;
//设置阴影贴图模糊度
pointLight.shadow.radius = 20;
//设置阴影贴图的分辨率(让它变得更加细致)
pointLight.shadow.mapSize.set(512, 512);

scene.add(pointLight);

然后我们可以用gui控制点光源的部分属性。

gui.add(pointLight.position, "x").min(-5).max(5).step(0.1);
gui.add(pointLight, "distance").min(0).max(5).step(0.001);

gui.add(pointLight, "decay").min(0).max(1).step(0.1);

我们做出一个灯光,但是看不到灯光的源头,不过我们可以做一个更小的小球,来模拟灯光的出口,并且可以利用它做出一些效果。

const smallBox = new THREE.Mesh(
  new THREE.SphereGeometry(0.1, 20, 20),
  new THREE.MeshBasicMaterial({ color: 0xff0000 })
);
smallBox.position.set(2, 2, 2);
// 点光源
const pointLight = new THREE.PointLight(0xff0000, 2);
//光照强度
// pointLight.intensity = 2;
// 设置直线光源产生阴影
pointLight.castShadow = true;
//设置阴影贴图模糊度
pointLight.shadow.radius = 20;
//设置阴影贴图的分辨率(让它变得更加细致)
pointLight.shadow.mapSize.set(512, 512);

smallBox.add(pointLight);
scene.add(smallBox);

我们可以利用时钟。来让这个点光源旋转。

//设置时钟
const clock = new THREE.Clock();
//渲染函数
function render() {
  let time = clock.getElapsedTime();
  //通过时间设置小球的位置
  smallBox.position.x = Math.sin(time) * 3;
  smallBox.position.z = Math.cos(time) * 3;
  smallBox.position.y = 2 + Math.sin(time*10);


  controls.update();
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}

点光源全部代码

//点光源(灯泡) 和 聚光灯(手电筒)
//导入 threejs
import * as THREE from "three";
//导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
//导入lil.gui
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(
  45, // 视角
  window.innerWidth / window.innerHeight, // 宽高比 窗口的宽高进行设置的
  0.1, // 近平面   相机最近最近能看到的物体
  1000 // 远平面   相机最远能看到的物体
);
//设置相机位置
camera.position.set(0, 0, 10);
scene.add(camera);
// 监听窗口的变化 重新设置渲染器的大小 画布自适应窗口
window.addEventListener("resize", () => {
  // 重新设置渲染器的大小
  renderer.setSize(window.innerWidth, window.innerHeight);
  // 重新设置相机的宽高比
  camera.aspect = window.innerWidth / window.innerHeight;
  // 重新计算相机的投影矩阵
  camera.updateProjectionMatrix();
});
//创建gui实例
const gui = new GUI();
// 做一个球体
const SphereGeometry = new THREE.SphereGeometry(1, 20, 20);
// 材质
const material = new THREE.MeshStandardMaterial();
const sphere = new THREE.Mesh(SphereGeometry, material);
// 投射阴影
sphere.castShadow = true;
scene.add(sphere);
// 创建平面
const planeGeometry = new THREE.PlaneGeometry(50, 50);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
plane.receiveShadow = true;
// 接收阴影
scene.add(plane);
// 灯光
// 环境光
const light = new THREE.AmbientLight(0xffffff);
const smallBox = new THREE.Mesh(
  new THREE.SphereGeometry(0.1, 20, 20),
  new THREE.MeshBasicMaterial({ color: 0xff0000 })
);
smallBox.position.set(2, 2, 2);
// 点光源
const pointLight = new THREE.PointLight(0xff0000, 2);
pointLight.position.set(2, 2, 2);
//光照强度
// pointLight.intensity = 2;
// 设置直线光源产生阴影
pointLight.castShadow = true;
//设置阴影贴图模糊度
pointLight.shadow.radius = 20;
//设置阴影贴图的分辨率(让它变得更加细致)
pointLight.shadow.mapSize.set(512, 512);
smallBox.add(pointLight);
scene.add(smallBox);
scene.add(light);
gui.add(pointLight.position, "x").min(-5).max(5).step(0.1);
gui.add(pointLight, "distance").min(0).max(5).step(0.001);
gui.add(pointLight, "decay").min(0).max(1).step(0.1);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器的大小  (窗口大小)
renderer.setSize(window.innerWidth, window.innerHeight);
// 开启场景中的阴影贴图
renderer.shadowMap.enabled = true;
// 将渲染器的dom元素添加到body中
document.body.appendChild(renderer.domElement);
//添加世界坐标辅助器  (红色x轴,绿色y轴,蓝色z轴)一个线段 参数为 线段长度
const axesHelper = new THREE.AxesHelper(6);
//添加到场景之中
scene.add(axesHelper);
// 添加轨道控制器 (修改侦听位置)  一般监听画布的事件  不监听document.body
const controls = new OrbitControls(camera, renderer.domElement);

//设置时钟
const clock = new THREE.Clock();
//渲染函数
function render() {
  let time = clock.getElapsedTime();
  //通过时间设置小球的位置
  smallBox.position.x = Math.sin(time) * 3;
  smallBox.position.z = Math.cos(time) * 3;
  smallBox.position.y = 2 + Math.sin(time*10);
  controls.update();
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}

//渲染
render();

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Web阿成

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值